聊聊Spring中的ConfigurationClassPostProcessor

 之前有讲到过在Spring中有各种各样的BeanFantoryPostProcessor后置处理器,在这些后置处理器中有一个对于Spring使用java Config起着至关重要的后置处理器,他就是ConfigurationClassPostProcessor,因为通过他的一个方法postProcessBeanDefinitionRegistry会进行类的扫描以及注册,在这个方法中对于配置类进行各种处理并且注册。如果没有这个类可以说spring基本无法使用java config的开发模式。接下来聊下这个类的这个方法究竟做了什么。
 进入到这个方法中可以看到他会调用另外一个方法processConfigBeanDefinitions如图:
在这里插入图/片描述
在processConfigBeanDefinitions()会调用registry.getBeanDefinitionNames();来获取到所有的已经注册到容器中的所有bd名字这里如果我们只做了注入Appconfig的操作并且只注入了一个,此时只会有七个beandefinition,那就是上次讲到的六个后置处理器和一个Appconfig的描述,然后开始对这七个类进行循环处理,如图:
在这里插入图片描述
然后在else if分支中会进行一个判断来确定是否需要将BeanDefinitionHolder添加到configCandidates集合中,在这个判断中主要是对是否加了@Configuration或者是加了@Component、@ComponentScan、@Import、@ImportResource或者是方法上加了@Bean的注解。
在这里插入图片描述
只要满足上边的条件都会返回true否则返回false。如果真的返回了false那么此时方法就会判断configCandidates为空就不会再继续执行。然后接下来开始循环解析配置类(如红框所示):
在这里插入图片描述
在parse()方法中我们可以看到又调用了parse的重载方法:
在这里插入图片描述
最终会来到processConfigurationClass(ConfigurationClass configClass) 这个方法中,在这个方法中首先处理了本类被别的类引入的情况,然后递归调用了doProcessConfigurationClass(configClass, sourceClass)这个方法,如图:
在这里插入图片描述
进入到这个方法中然后首先处理了内部类,然后处理注解@PropertySource之后再之后处理@ComponentScan注解最后再处理所有的@Bean的方法。我们主要看下对于最后这三种注解的处理,首先是@ComponentScan:
在这里插入图片描述
在这个逻辑中解析了所有的被扫描的包以及被扫描的类,如果是普通的类就会经过一些逻辑以后直接转为BeanDefinition然后注册进入bean工厂,如果还是一个配置了那么就会从新进行配置类的处理,关于这个地方就不再展开进行分析了,我们继续循着主逻辑前进,然后解析来是对@Import的处理对于这一块的处理主要分为了三部分,一部分是当这个注解引入的是ImportSelector另外一种是ImportBeanDefinitionRegistrar最后是普通类进入processImports后如图:
在这里插入图片描述
此时的处理是稍微有些区别的,如果是ImportSelector的话那么就会调用其模板方法selectImports然后返回所有需要放入容器的类的集合,然后调用之前调用过的一个方法processConfigurationClass将这些类放入到map集合中这个map集合是this.configurationClasses如果imprt的普通类也会这样处理,但是如果引入的是ImportBeanDefinitionRegistrar会将引入的Registar放入到一个map中这个map是this.importBeanDefinitionRegistrars,处理完了@Import以后就要处理@Bean注解了:
在这里插入图片描述
将所有的带有@Bean注解的方法进行包装以后放入到configClass中。至此回到一开始通过parse方法进来的地方,这个解析类的分支就处理完了,当然有很多细节没有提到。然后我们回到最开始的parse()方法。然后在解析完成之后调用了loadBeanDefinitions方法:
在这里插入图片描述
一直执行到此处我们可以知道此时的configClasses包括了当前的配置类以及通过ImportSelector读取的类的数组,在这个loadBeanDefinitions方法中将所有的类转换成BeanDeifinition并且注入到容器中,并且处理了配置类的@Bean的方法,将方法的返回值搞成BeanDefinition并且注册给容器,值得注意的是在此处分为了静态的方法和非静态的方法实现,如果是静态的就给了一个FactoryMethodName的赋值,过于工厂方法这里就不再做描述了,这个地方也是对于bean的生成起着至关重要的作用。同时在loadBeanDefinitions方法中我们还执行了所有的ImportBeanDefinitionRegistrar的registerBeanDefinitions方法。至此我们回到主线继续前进,在接下来的逻辑中由于我们又往容器中注入了很多的BeanDefinition所以需要继续对新的beanDefinition进行处理,看看他们是不是配置类的beanDefinition这样来循环处理直至set集合为空。如图:
在这里插入图片描述
以上便是ConfigurationClassPostProcessor这个bean工厂后置处理器的第一个方法postProcessBeanDefinitionRegistry执行的时候的逻辑,在我们之前介绍的后置处理器的流程中还会有一个bean工厂后置处理器的方法会随着工厂的启动而执行,他就是postProcessBeanFactory,在ConfigurationClassPostProcessor的这个方法中他会根据配置类是full或者lite来决定是否对这个配置类进行从glib代理,如图:
在这里插入图片描述
对于配置类的full和lite的区别就是如果加了@Configration的注解就会是fulll如果只是加了之前提到的几种注解或者是只有@Bean的方法那么就会是lite此时这个逻辑中只会对是full的配置类进行cglib的代理。如图:
在这里插入图片描述
最后会通过 enhancer.enhance方法完成对于加了@Configration注解的配置类。那为什么spring要做这个操作呢,通过验证以后发现如果不生成代理类则如图的代码会有不同的执行结果:
在这里插入图片描述
此时如果不产生代理,则此时IndexDao1则会实例化两边也是就是会执行两次构造方法,但是如果加了@Configration注解则此时只会执行一遍IndexDao1的构造方法。通过阅读源码其实会发现通过cglib增强以后会去判断一下执行的方法和调用的方法是不是同一个方法,以此来判断是需要get还是需要new。如图:
在这里插入图片描述
以上便是对ConfigurationClassPostProcessor的方法的解析,如有不对的地方请见谅,当然同样有很多细节已经进行了隐藏,因为展开的话篇幅太大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值