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的动态代理

posted @ 2023-01-07 11:46  雩娄的木子  阅读(45)  评论(0编辑  收藏  举报