Configuration源码,你了解多少?( 二 )

再看下ProxyConfiguration配置的情况:
public class Tests {    @Test    public void runConfig() {        log.info("configuration: {}", proxyConfiguration); // 1、CGLIB代理的对象        log.info("Configuration中的Bean: {}", proxyConfiguration.dogCage() == proxyConfiguration.dogCage()); // 2、两次结果相同        log.info("容器中的Bnea: {}", beanFactory.getBean(DogCage.class) == beanFactory.getBean(DogCage.class));// 3、从Spring容器中取值都是一样的        animalCage.cages.forEach(cage -> {            if (cage instanceof DogCage) {                log.info("dogCage : {} ", cage == dogCage); // 和上面的对象不一致,非单例            }        });    }}会得到这样的现象:

  1. proxyBeanMethods = true时,从Spring容器中取出的Configuration是一个Cglib代理配置,否则是一个原始类型配置
  2. proxyBeanMethods = true时 , 多次调用Bean方法,每次都是一个新对象 , 否则都是同一个对象
  3. 从Spring容器中取出Bean,不管多少次,都是同一个对象,也就是单例的
Lite Full Mode看到上面的现象后,我们有必要了解下Spring配置中的Lite和Full两种模式
lite模式包含:
  • 被@Component修饰的类
  • 通过@ComponentScan扫描的类
  • 通过@Import导入的配置类
  • 通过@ImportResource导入的Spring配置文件
  • 没有任何Spring相关注解,类里面有@Bean修饰的方法
  • 被@Configuration修饰,但proxyBeanMethods = false
full模式包含:
  • 被@Configuration修饰,且属性proxyBeanMethods = true(默认)
full模式使用特性:
  • full模式下的配置类会被Cglib代理生成代理类取代原始类型保存到在容器中
  • full模式下的@Bean方法不能是private和final,因为方法会被重写
  • 单例scope下不同@Bean方法可以互相引用,实现单实例的语义
lite模式使用特性:
  • lite模式下的配置类不生成代理,原始类型进入容器
  • lite模式下的@Bean方法可以是private和final
  • 单例scope下不同@Bean方法引用时无法做到单例,通过@Bean方法生成的对象都是新的实例
结束语@Configuration(proxyBeanMethods = false)的配置其实是Lite模式 , 这种模式下,配置类不会生成代理类,速度会更快,但是要注意,在配置类中的@Bean方法,不能用来实现单例级别的依赖 。

【Configuration源码,你了解多少?】


推荐阅读