SpringBoot之@Configuration详解

  1. 添加了 @Configuration 的类是 SpringBoot 的配置类,这个配置类等价于 Spring 的 beans.xml 配置文件;在配置类中可以使用 @Bean 注解定义 Bean 对象;如下我们定义了一个 AppConfig.class 配置类

public class AppConfig {
    // 声明一个名为 user 的 Bean 对象
    
    public User user() {
        return new User();
    }
}
  1. 配置类对于 SpringBoot 来说,也是一个组件;可以启动类中拿到容器验证一下容器中是否有该组件

public class SpringbootStudyApplication {
    public static void main(String[] args) {
        // 1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
        // 2.查看容器里的组件
        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            if(beanName.equals("appConfig")) {
                System.out.println("AppConfig 是一个组件");
                break;
            }
        }
    }
}
  1. 配置类中调用 Bean 对象定义方法可得到对应 Bean 对象,即使多次调用,返回的是同一个对象

public class SpringbootStudyApplication {
    public static void main(String[] args) {
        // 1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
        // 2.返回 AppConfig 对象
        AppConfig appConfig = (AppConfig)context.getBean("appConfig");
        // com.study.springboot.config.AppConfig$$EnhancerBySpringCGLIB$$9b3d45d3@3003697
        System.out.println(appConfig); 
        // 3.调用 user() 方法拿出两个 user Bean 对象进行比较
        User user1 = appConfig.user();
        User user2 = appConfig.user();
        System.out.println(user1 == user2); // true
        System.out.println(user1); // com.study.springboot.entity.User@6826c41e
        System.out.println(user2); // com.study.springboot.entity.User@6826c41e
    }
}

这是因为配置类上添加了 @Configuration 注解,容器中的 appConfig Bean对象不是普通对象,而是一个代理对象(CGLIB 增强代理对象),从上面打印出的 appConfig 可以看出;代理对象调用 user() 方法,SpringBoot 总会检查 user() 返回的 User 对象在容器中是否已经存在,如果存在就直接返回容器中的 User Bean 对象

  1. 我们进入 @Configuration 注解,发现该注解除了 value 属性,还有一个 proxyBeanMethods 属性,且默认值为 true
boolean proxyBeanMethods() default true;

该配置表示添加了 @Configuration 的配置类中的所有方法都是代理对象方法,如果我们把该选项设置为 false,那么第 3 步中 user1 != user2;AppConfig 也不是代理对象,而是普通对象


public class SpringbootStudyApplication {
    public static void main(String[] args) {
        // 1.返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootStudyApplication.class, args);
        // 2.返回 AppConfig 对象
        AppConfig appConfig = (AppConfig)context.getBean("appConfig");
        System.out.println(appConfig); // com.study.springboot.config.AppConfig@20921b9b
        // 3.调用 user() 方法拿出两个 user Bean 对象进行比较
        User user1 = appConfig.user();
        User user2 = appConfig.user();
        System.out.println(user1 == user2); // false
        System.out.println(user1); // com.study.springboot.entity.User@867ba60
        System.out.println(user2); // com.study.springboot.entity.User@5ba745bc
    }
}

所以,如果存在组件依赖的情况,例如:事务依赖于连接池,这里就必须要设置为 @Configuration(proxyBeanMethods = true);这也是事务失效的一个原因!如果组件之间没有依赖,可以设置proxyBeanMethods = false,这将有助于提高容器初始化速度。

你可能感兴趣的:(#,springBoot,spring,boot,java,spring)