ConfigurationClassPostProcessor源码rock_fish
Spring大观园,我有过的困惑或许你也有!
导读
1.是谁在何时注册了ConfigurationClassPostProcessor ?
2.是谁在何时调用ConfigurationClassPostProcessor?
3.ConfigurationClassPostProcessor的作用
1.是谁在何时注册了ConfigurationClassPostProcessor
- AnnotationConfigApplicationContext 构造函数中创建了AnnotatedBeanDefinitionReader。
- AnnotatedBeanDefinitionReader 的构造函数中注册注解配置类的处理器,其中有ConfigurationClassPostProcessor。
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
跟进源码查看,可见
if(!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)){// 在这里注册了ConfigurationClassPostProcessor类。
RootBeanDefinitiondef=newRootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 调用registerPostProcessor来进行注册
beanDefs.add(registerPostProcessor(registry,def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
2.是谁在何时调用ConfigurationClassPostProcessor?
笔记invokeBeanFactoryPostProcessors源码分析中,可以快速找到答案
3.ConfigurationClassPostProcessor的作用(本篇重点)
publicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){// 开始注册Config类中定义的BeanDefinition
processConfigBeanDefinitions(registry);
}
筛选代码来梳理,有3个关键逻辑
1.筛选出候选配置类
2.解析配置类 parser.parse(candidates)
3.加载配置类中引入的BeanDefinition this.reader.loadBeanDefinitions(configClasses);
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry){ List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
// 将配置类放在configCandidates列表中。部分代码省略...
for(String beanName : candidateNames){
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//被处理过的配置类的定义中,会被打Full、Lite属性标记。
if(ConfigurationClassUtils.isFullConfigurationClass(beanDef)||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)){
logger.debug("Bean definition has already been processed as a configuration class: "+ beanDef);
}
//筛选出配置类,放置到configCandidates(配置候选者)中
elseif(ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef,this.metadataReaderFactory)){
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 创建配置类的分析器,对配置类进行分析。配置类就是我们添加了@Configuration注解的类,可以有多个的,通常springboot项目中是启动类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory,this.problemReporter,this.environment,
this.resourceLoader,this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
do{
// 开始分析配置类
parser.parse(candidates);
parser.validate();
// Read the model and create bean definitions based on its content
if(this.reader ==null){
this.reader = new ConfigurationClassBeanDefinitionReader(
registry,this.sourceExtractor,this.resourceLoader,this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 加载BeanDefinition
this.reader.loadBeanDefinitions(configClasses);
}
while(!candidates.isEmpty());
}
配置类的判断
ConfigurationClassUtils.checkConfigurationClassCandidate
、Full
、Lite
后边在说parser.parse(candidates) 跟踪到关键方法processConfigurationClass
protectedvoidprocessConfigurationClass(ConfigurationClass configClass)throwsIOException{// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass =asSourceClass(configClass);
do{
// 循环处理配置类
sourceClass =doProcessConfigurationClass(configClass, sourceClass);
}
while(sourceClass !=null);
this.configurationClasses.put(configClass, configClass);
}
细节可以查看,跟着节奏自己捋一遍源码配置类解析源码解析-脑图版
作者:rock_fish
链接:https://www.jianshu.com/p/3674509b916a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上是 ConfigurationClassPostProcessor源码rock_fish 的全部内容, 来源链接: utcz.com/z/514400.html