ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor,所以他是BeanFactory的后置处理器的一种,也是非常重要的一个BeanFactory的后置处理器。我们看看他到底做了哪些事情。
BeanFactoryPostProcessor的流程顺序我们已经讲过了,我们现在从ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法开始看。
这个方法有两个事情,一个是registriesPostProcessed添加了registryId,这个是后面用于postProcessBeanFactory方法中判断是否已经执行了processConfigBeanDefinitions方法。这里肯定会执行,所以postProcessBeanFactory方法就不再执行。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 其他略
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
processConfigBeanDefinitions方法是比较核心的方法,我这里就不贴很多代码,通过流程图的方式讲解这里做了什么。具体的例子参考之前的文章spring学习之bean的定义。
@Configuration
首先,他会获取@Configuration注解,他实际上是继承了@Component。然后再解析@Configuration类中的其他注解。所以我们经常在类上写的@Configuration之所以会注入到容器中,就是这里被解析的。
解析的过程是在ConfigurationClassParser的parser方法中,解析的结果存入BeanDefinition。parser最后调用比较重要的方法是doProcessConfigurationClass。
@Conditional
doProcessConfigurationClass方法是在processConfigurationClass方法中调用的,processConfigurationClass方法中有一个比较重要的注解判断,@Conditional,用于判断是否存入BeanDefinition。我们常用的@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnClass、@ConditionalOnMissingClass、@Conditional等就是ConditionEvaluator#shouldSkip方法来判断的,如果符合条件,才可以解析下面的几个注解。
@PropertySource
我们需要引入资源配置文件的时候,经常用以下的写法,他能被注入到各个属性,就是在doProcessConfigurationClass这个方法中实现的。
@Configuration
@PropertySource("classpath:***.properties")
public class XXXConfig {
}
@ComponentScans和@ComponentScan
这两个注解的basePackages下面的类,就是这里在这里扫描,由于可能扫描的类中,也有这两个注解,所以这个方法里会通过递归调用parse方法。
Import
spring学习之bean的定义
在这里演示了import的三种方式,包括@Import注解、实现ImportBeanDefinitionRegistrar接口、实现ImportSelector。这三种为什么能被注入容器,就是在ConfigurationClassParser的processImports方法解析。
首先是解析ImportSelector接口,然后是ImportBeanDefinitionRegistrar接口,最后是
@Import注解。
@ImportResource
当我们需要引入其他的spring配置文件时,我们会用@ImportResource注解,也是在这里解析的。
@ImportResource({ "classpath *:XXX.xml"})
public class MyConfig {
}
@Bean
最后是@Bean,我们在代码里注入的bean的定义。
所以ConfigurationClassPostProcessor其实做了很多事情,上面几个注解会把解析后的信息加入到BeanDefinition,后面getBean的时候,就会调用这里BeanDefinition的内容。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。