ConfigurationClassParser 是如何工作的 ?
简介
Spring的工具类 ConfigurationClassParser 用于分析一个 @Configuration 注解的类,产生一组ConfigurationClass对象。其分析过程主要是递归分析注解中隐含的@Import,找出其中所有的配置类,然后返回这组配置类。
这个工具类自身的逻辑并不会注册Bean定义,但是它用到了另外一个工具ComponentScanAnnotationParser在执行时会做Bean定义注册。
一般情况下一个@Configuration注解的类只会产生一个ConfigurationClass对象,但是因为@Configuration注解的类可能会使用另外一个注解@Import引入其他配置类,所以总的来看,ConfigurationClassParser分析一个 @Configuration注解的类,可能产生任意多个ConfigurationClass对象。
这个工具类分离了两个不同点关注点 :
@Configuration注解的类的结构分析
注册BeanDefinition对象
主要功能分析
公开方法 parse() 外部调用入口
/**
* 总体工作流程 :
* 1. 外部提供参数 configCandidates , 是一组需要被分析的候选配置类 ;
* 2. 调用该类的 parse() 方法, parse() 方法针对每个候选配置类,递归查找其注解@Import,
* 以及注解的注解中的@Import,然后处理这些@Import,每个@Import可能对应一个ImportSelector,
* ImportBeanDefinitionRegistrar,或者是另外一个@Configuration注解的配置类,parse()会
* 递归处理这些进一步的导入,直到所有所有的这些配置类都被发现,这些发现的每个ConfigurationClass,
* 会被记录到 configurationClasses;
* 3. 外部通过调用该类的方法 getConfigurationClasses() 获得分析过程中保存在 configurationClasses
* 中的配置类;
* @参数 configCandidates : 外部指定需要被分析的一组候选配置类
**/
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 这里根据Bean定义的不同类型走不同的分支,但是最终都会调用到方法
// processConfigurationClass(ConfigurationClass configClass)
if (bd instanceof AnnotatedBeanDefinition) {
// bd 是一个 AnnotatedBeanDefinition
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
// bd 是一个 AbstractBeanDefinition,并且指定 beanClass 属性
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
// 其他情况
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 执行找到的 DeferredImportSelector
processDeferredImportSelectors();
}保护方法 processConfigurationClass()分析一个配置类
私有方法 processDeferredImportSelectors() 处理需要延迟处理的ImportSelector
私有方法 doProcessConfigurationClass()对一个配置类执行处理和构建的主逻辑
私有方法 processImports()处理配置类上搜集到的@Import注解
Last updated
Was this helpful?