您的位置:首页 > 编程语言 > Java开发

Spring ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() 是如何工作的 ?

2017-11-20 09:58 661 查看

功能

ConfigurationClassPostProcessor 位于 org.springframework.context.annotation 包中,这是一个 BeanFactoryPostProcessor ,用于 Spring应用启动过程中 @Configuration 类的处理 。

何时被引入

非Springboot的Sping应用,当在配置文件中使用

<context:annotation-config/>


或者

<context:component-scan/>


时,该BeanFactoryPostProcessor 会被注册。

Springboot 应用,在ApplicationContext对象创建时,会调用 AnnotationConfigUtils.registerAnnotationConfigProcessors() 注册这个BeanFactoryPostProcessor。

postProcessBeanDefinitionRegistry() 何时被执行

BeanFactoryPostProcessor ConfigurationClassPostProcessor 拥有最高执行优先级 Ordered.HIGHEST_PRECEDENCE ,因为配置类中定义的每个Bean方法必须要在其它的BeanFactoryPostProcessor被执行之前先通过ConfigurationClassPostProcessor 注册到容器中去。

AbstractApplicationContext.run()方法执行过程中,在BeanFactory被准备(prepare)和postProcess之后,

AbstractApplicationContext的invokeBeanFactoryPostProcessors()方法被调用,这个方法用来执行所有

容器中被作为Bean注册BeanFactoryPostProcessor,其中就包括对 ConfigurationClassPostProcessor 方法postProcessBeanDefinitionRegistry()的执行。

// 调用链
AbstractApplicationContext.refresh()
=> invokeBeanFactoryPostProcessors()
=> ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
=> processConfigBeanDefinitions()


postProcessBeanDefinitionRegistry()执行过程

ConfigurationClassPostProcessor 的执行是其BeanDefinitionRegistryPostProcessor接口方法 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 被调用。

其执行过程的主要逻辑就是使用工具ConfigurationClassParser尝试发现所有的配置(@Configuration)类,使用工具ConfigurationClassBeanDefinitionReader注册所发现的配置类中所有的Bean定义。结束执行的条件是所有配置类都被处理相应的Bean定义注册到容器。

/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);

processConfigBeanDefinitions(registry);
}

/**
* Build and validate a configuration model based on the registry of
* Configuration classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 用来记录候选配置类
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
// 将容器中已经登记的Bean定义作为候选配置类名称
String[] candidateNames = registry.getBeanDefinitionNames();

for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 如果这个Bean定义有注解@Configuration,将其记录为候选配置类
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}

// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
// 一个候选配置类都没有找到,直接返回
return;
}

// Sort by previously determined @Order value, if applicable
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});

// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}

// Parse each @Configuration class,现在准备要分析配置类了
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

// 表示将要被处理的候选配置类
// 因为不清楚候选是否确实是配置类,所以使用BeanDefinitionHolder类型记录
// 这里初始化为方法开始时容器中注解了@Configuration的Bean定义的集合
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
// 表示已经处理的配置类,已经被处理的配置类已经明确了其类型,所以用ConfigurationClass类型记录,
// 这里初始化为空
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
// 分析配置类,分析过程中
// 1. 如果遇到注解了@Component类,直接作为Bean定义注册到容器
// 2. 如果注解或者注解的注解中有@Import, 处理所有这些@import,识别配置类,
//    添加到分析器的属性configurationClasses中去
parser.parse(candidates);
parser.validate();

// 从分析器parser中获取分析得到的配置类configurationClasses

c988
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);

// 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());
}
// 使用 ConfigurationClassBeanDefinitionReader reader 从 configClasses 中加载
// Bean定义并注册到容器
this.reader.loadBeanDefinitions(configClasses);
// 刚刚处理完的配置类记录到已处理配置类alreadyParsed
alreadyParsed.addAll(configClasses);

// 清空候选配置类集合,为下一轮do循环做初始化准备
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 经过一轮do循环,现在容器中Bean定义数量超过了该次循环开始时的容器内Bean定义数量,
// 说明在该次循环中发现并注册了更多的Bean定义到容器中去,这些新注册的Bean定义
// 也有可能是候选配置类,它们也要被处理用来发现和注册Bean定义
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<String>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 在新注册的Bean定义中找到一个候选配置类
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());// 一直循环到没有新的候选配置类被发现

// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}


相关资料

缺省配置Springboot Web应用启动过程中Bean的登记

ConfigurationClassPostProcessor 官方文档

AbstractApplicationContext.invokeBeanFactoryPostProcessors()

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐