Bean的注册
在上一篇文章中提到了在使用invokeBeanFactoryPostProcessors(beanFactory) 方法中,
调用了 ConfigurationClassPostProcessor 中的 postProcessBeanDefinitionRegistry 方法,
实现了对configuration配置文件中的内容得到加载和解析。完成对标注为Bean的方法注册「regist」到容器中。
下面就针对这一注册配置文件内的Bean的过程进行源码的分析:
ConfigurationClassPostProcessor
在 invokeBeanFactoryPostProcessor 方法中,
循环调用类中的后置方法 postProcessBeanDefinitionRegistry ,
其中包括了 ConfigurationClassPostProcessor 类。
根据名字也能看出这个类是配置文件类的后置处理类。那么就之间看代码,了解配置文件的后置处理器都做了些什么。
1  | public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {  | 
下面对 processConfigBeanDefinitions 中的方法一步一步看:
使用processConfigBeanDefinitions解析注册Bean
1  | public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {  | 
上述代码完成了的过程大致分为这几步
- 找出Config配置类,包括使用@Configuration注解标注的配置类
 - 根据@Order进行进行顺序的调整
 - 解析所有的@Configuration内的Bean,完成对配置类中所有 Bean的注册。
 - 验证并进行标记Bean已经被解析注册
 
其中最重要的就是第3步,需要找出Bean,并进行注册
parse方法解析并完成注册Bean的。
1  | public void parse(Set<BeanDefinitionHolder> configCandidates) {  | 
如果使用注解方式进行配置类的配置的情况,最后会调用 processConfigurationClass 方法进行处理。
1  | protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {  | 
最后会递归使用 doProcessConfigurationClass 进行处理配置类和其超类.
1  | protected final SourceClass doProcessConfigurationClass(  | 
总结在使用 doProcessConfigurationClass 方法时,大致会有这样几步:
- 如果标记有 
@Component注解,则会先去递归处理成员类,那么他是如何进行递归处理的呢,看主要方法的调用就能够理解:
processMemberClasses -> processConfigurationClass -> doProcessConfigurationClass -> processMemberClasses
每次都会递归的先处理成员类。 - 处理 
@PropertySource注解,作用为加载指定的配置文件 - 处理所有的 
@ComponentScan注解,如果配置文件中标记有@ComponentSacn或者@ComponentScans注解的话,会先去解析对应路径下的Bean,包装成BeanDefinitionHolder再次进行parse。 - 处理所有的 
@Import注解,处理所有使用Import注解引入的配置文件 - 处理所有的 
@ImportResource注解 - 处理所有 
@Bean方法,添加为 BeanMethod,解析配置文件中配置为@Bean的方法,添加到configClass中的BeanMethod中 - 处理接口的默认方法
 - 按照以上逻辑进行递归的处理超类。
 
在方法中,可以找时间画一张图来解析这个方法真正做了写什么。[todo] 。
注册的精简过程
最后的parse方法是关键,经过以上步骤可以,在本章节需要特别注意的是 @ComponentSacn 和 处理所有的 @Bean 这两步:
在处理 @ComponentSacn 中,将直接将根据路径解析出来的Bean使用 componentScanParser.parse 方法,最终在 registerBeanDefinition() 方法中注册进去。
而在处理@Bean方法的时候,是将Bean方法包装成BeanMethod 放到 this.beanMethods 中,等待在 parse() 后 this.reader.loadBeanDefinitions(configClasses); 中进行操作.
而在前面说的loadBeanDefinitions 中会将前面提到的 Import、ImportReource和 BeanMethod 统一进行注册。
1  | if (configClass.isImported()) {  | 
在loadBeanDefinitionsForBeanMethod中,进行了对解析出来的使用@Bean标注的方法进行注册。从而完成注册Bean的主线功能。不具体进行梳理这个方法的过程,大致为构建一个BeanDefintion后,通过registerBeanDefinition方法进行注册,放到beanDefinitionMap中。