SpringBoot @Configuration与@Bean注解使用介绍

 更新时间:2022年10月13日 15:44:43   作者:一根头发学一年  
这篇文章主要介绍了SpringBoot中的@Configuration与@Bean注解,在进行项目编写前,我们还需要知道一个东西,就是SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制,只有把这些都搞清楚了,我们在之后使用才会更加得心应手

之前我们都是通过xml的方式定义bean,里面会写很多bean元素,然后spring启动的时候,就会读取bean xml配置文件,然后解析这些配置,然后会将这些bean注册到spring容器中,供使用者使用。

Spring3.0开始,@Configuration用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean注解联合使用。

@Configuration注解可以加在类上,让这个类的功能等同于一个bean xml配置文件。

@Bean注解类似于bean xml配置文件中的bean元素,用来在spring容器中注册一个bean。

demo示例

1.创建一个工程

2.创建bean文件夹并创建两个示例用户和部门

如下:

用户

package com.example.ethan.bean;
public class User {
    private String name;
    private Integer age;
    private Dept dept;
	public User() {
	}
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

部门

package com.example.ethan.bean;
public class Dept {
    private String name;
    public Dept(String name) {
        this.name = name;
    }
}

3.创建配置类

使用@Configuration注解,并使用@Bean注解创建bean

package com.example.ethan.config;
import com.example.ethan.bean.Dept;
import com.example.ethan.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration  //告诉SpringBoot这是一个配置类 == 配置文件
public class ConfigDemo {
    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        return zhangsan;
    }
    @Bean("my rd")
    public Dept rd(){
        return new Dept("研发部");
    }
}

4.在主程序查看

编写主程序,查看容器中的Bean

package com.example.ethan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class EthanApplication {
    public static void main(String[] args) {
        // 返回ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(EthanApplication.class, args);
        // 查看容器组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        System.out.println("========================");
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
}

运行后可以看到configDemo、user01、my rd都已经被容器管理。

特点和特性

1.配置类本身也是组件,也会有被IOC容器管理的Bean,且是一个单实例的代理对象。

在主程序验证代码如下:

ConfigDemo bean = run.getBean(ConfigDemo.class);
 System.out.println(bean);

// 结果:com.example.ethan.config.ConfigDemo$$EnhancerBySpringCGLIB$$24eef7b3@a619c2

可以看到得到的bean是一个CGLIB代理对象。

2.默认被IOC容器管理@Bean注解产生的Bean是单实例的。

在主程序验证代码如下:

Dept d1 = run.getBean("my rd", Dept.class);
Dept d2 = run.getBean("my rd", Dept.class);
System.out.println("组件:"+(d1 == d2));
// 组件:true

结果为true,证明@Bean注解产生的Bean是单实例的。

3.@configration的proxyBeanMethods属性。

这个属性默认为true。他的意思就是,当从容器获取Bean时,是否用上面第1点中的代理对象调用方法获取bean。

增加验证如下:

	ConfigDemo bean = run.getBean(ConfigDemo.class);
    System.out.println(bean);
	// 如果@Configuration(proxyBeanMethods = true)代理对象调用方法
    User user = bean.user01();
    User user1 = bean.user01();
    System.out.println(user == user1);

当configration的proxyBeanMethods=true时,结果为true,否则结果为false。
也就是,当proxyBeanMethods=true,使用代理对象获取Bean,代理会拦截所有被@Bean修饰的方法,默认情况(bean为单例)下确保这些方法只被调用一次,放进容器,然后从容器查找到,就会直接使用,从而确保这些bean是同一个bean,即单例的。

否则,不使用代理对象获取Bean,每次获取都新建,所以两个Bean不相等。

这样做的主要目的是为了解决组件依赖问题,比如下面的部门被用户
依赖,可以保证用户依赖的部门是单实例。

验证代码如下:

首先让用户依赖部门

package com.example.ethan.config;
import com.example.ethan.bean.Dept;
import com.example.ethan.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods=true)  //告诉SpringBoot这是一个配置类 == 配置文件
public class ConfigDemo {
    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        //user组件依赖了Dept组件
        zhangsan.setDept(rd());
        return zhangsan;
    }
    @Bean("my rd")
    public Dept rd(){
        return new Dept("研发部");
    }
}

然后测试用户依赖的组件是否是容器中的Bean

	User user01 = run.getBean("user01", User.class);
    Dept dept = run.getBean("tom", Dept.class);
    System.out.println("用户的宠物:"+(user01.getDept() == dept));
    // // 用户的部门:true

测试可以看到,当proxyBeanMethods=true时,结果为true,否则为false。

当proxyBeanMethods=true时也称为 Full模式,否则称为Lite模式。

Full(proxyBeanMethods = true)【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
组件依赖必须使用Full模式默认。其他默认是否Lite模式。
最佳实战

  • 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
  • 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

到此这篇关于SpringBoot @Configuration与@Bean注解使用介绍的文章就介绍到这了,更多相关SpringBoot @Configuration与@Bean内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中跳出多重循环嵌套的三种方法

    Java中跳出多重循环嵌套的三种方法

    这篇文章主要给大家介绍了关于Java中跳出多重循环嵌套的三种方法,很多复杂的运算以及逻辑可能用到嵌套循环,但是如何跳出当前的多重嵌套循环,很多同学特别是新手都操作的不是很清楚,需要的朋友可以参考下
    2023-07-07
  • Java9新特性Module模块化编程示例演绎

    Java9新特性Module模块化编程示例演绎

    这篇文章主要为大家介绍了Java9新特性Module模块化编程的示例演绎,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-03-03
  • 在CentOS系统上安装Java JDK 8简单步骤

    在CentOS系统上安装Java JDK 8简单步骤

    最近购买一台新的云服务器,用于开发学习使用,因此需要安装很多的组件,下面这篇文章主要给大家介绍了关于在CentOS系统上安装Java JDK8的简单步骤,需要的朋友可以参考下
    2023-12-12
  • Java数据结构和算法之冒泡排序(动力节点Java学院整理)

    Java数据结构和算法之冒泡排序(动力节点Java学院整理)

    冒泡排序(Bubble Sort)是一种简单的排序算法。本文重点给大家介绍java数据结构和算法之冒泡排序,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-04-04
  • Java util.List如何实现列表分段处理

    Java util.List如何实现列表分段处理

    这篇文章主要介绍了Java util.List如何实现列表分段处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • idea启动spring项目中文乱码的解决方法

    idea启动spring项目中文乱码的解决方法

    本文主要介绍了idea启动spring项目中文乱码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Java 深入理解创建型设计模式之原型模式

    Java 深入理解创建型设计模式之原型模式

    原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节
    2022-02-02
  • 关于jackson序列化和feign返回值的问题

    关于jackson序列化和feign返回值的问题

    这篇文章主要介绍了关于jackson序列化和feign返回值的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringBoot整合mybatis使用Druid做连接池的方式

    SpringBoot整合mybatis使用Druid做连接池的方式

    这篇文章主要介绍了SpringBoot整合mybatis使用Druid做连接池的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Java面试必问之ThreadLocal终极篇分享

    Java面试必问之ThreadLocal终极篇分享

    ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量),这篇文章主要给大家介绍了关于Java面试必问之ThreadLocal终极篇的相关资料,需要的朋友可以参考下
    2021-10-10

最新评论