ConfigurationClassPostProcessor源码rock_fish

编程

Spring大观园,我有过的困惑或许你也有!

导读

1.是谁在何时注册了ConfigurationClassPostProcessor ?
2.是谁在何时调用ConfigurationClassPostProcessor?
3.ConfigurationClassPostProcessor的作用

1.是谁在何时注册了ConfigurationClassPostProcessor

  1. AnnotationConfigApplicationContext 构造函数中创建了AnnotatedBeanDefinitionReader。
  2. 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());

}

  1. 配置类的判断ConfigurationClassUtils.checkConfigurationClassCandidateFullLite 后边在说

  2. 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

回到顶部