ConfigurationClassParser 是如何工作的 ?
简介
主要功能分析
公开方法 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