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

2022-11-13 18:11:44 注解 介绍 springboot

之前我们都是通过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内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章