Spring之CGLIB对@Configuration注解的处理
CGLIB对@Configuration注解的处理
在ConfigurationClassPostProcessor完成了对整个上下文中的BeanDefinition扫描完成之后,按照Spring正常的思路来说,下面该根据BeanDefinition进行实例化创建bean了。
但是spring中比我们考虑的更多一步,spring考虑的是哪些bean可能存在着动态代理去进行实例化对象的情况呢?
是有的,比如说@Configuration对应的@Bean方法中就存在这种情况
@Configuration
public class MyConfig {}
如果这样子来进行配置的话,那么利用容器来获取得到这里的MyConfig并打印对应的类型
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean(MyConfig.class));
打印效果如下:
com.guang.spring.config.MyConfig$$EnhancerBySpringCGLIB$$163023f2@358c99f5
可以明显的看到是CGLIB代理
那么spring为什么要这样子来做呢?
看看下面这种情况
@Configuration
public class MyConfig {
@Bean
public AService aService(){
AService aService = new AService();
System.out.println(aService);
return aService;
}
@Bean
public BService bService(){
BService bService = new BService();
bService.setaService(aService());
return bService;
}
}
那么这种情况肯定是使用过的,通过测试发现
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean(MyConfig.class));
System.out.println(applicationContext.getBean(AService.class));
System.out.println(applicationContext.getBean(BService.class));
System.out.println(applicationContext.getBean(BService.class).getaService());
打印结果:
com.guang.spring.service.AService@145eaa29
com.guang.spring.config.MyConfig$$EnhancerBySpringCGLIB$$163023f2@358c99f5
com.guang.spring.service.AService@145eaa29
com.guang.spring.service.BService@3ee0fea4
com.guang.spring.service.AService@145eaa29
可以看到给BService中设置的属性aService对应的值是容器中的值
但是我们正常的认为:
@Configuration
public class MyConfig {
@Bean
public AService aService(){
AService aService = new AService();
System.out.println(aService);
return aService;
}
@Bean
public BService bService(){
BService bService = new BService();
bService.setaService(aService());
return bService;
}
}
在创建bService的过程中,因为调用了aService()方法,这里应该创建出来的是新的aService对象,但是通过打印并没有看到新的对象产生。
那么这是为什么呢?
根据上一篇文章的分析,对配置类的解析以及对配置类中的@Bean方法的解析,会将其变成BD。
首先分析一下解析配置类中的@Bean方法的过程:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod
解析@Bean标注了的方法,解析成BD并放入到BDMap中去
然后在org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanFactory中开始来对BD做是否需要进行代理的检测
因为对MyConfig这个类做了判断解析,标记为了full,所以下面因为会对这种来做处理
下面就开始来进行CGLIB的动态代理