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()
相关文章推荐
- 003-Spring4 扩展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
- 【spring源码分析】BeanDefinitionRegistryPostProcessor接口可自定义bean加入IOC
- Spring(24)——自定义BeanDefinitionRegistryPostProcessor
- Spring 工具类 ConfigurationClassParser 是如何工作的 ?
- Spring ConfigurationClassPostProcessor Bean解析及自注册过程
- ConfigurationClassBeanDefinitionReader 是如何工作的 ?
- 流程图解Spring Framework(五) Spring BeanFactoryPostProcessor如何工作的?
- 流程图解Spring Framework(六) Spring BeanPostProcessor如何工作的?
- Context namespace element 'annotation-config' and its parser class [org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser]
- Spring Boot Configuration Annotion Processor not found in classpath
- Spring:Configuration problem: Only one AsyncAnnotationBeanPostProcessor may exist within the context
- org.springframework.beans.factory.parsing.BeanDefinitionParsingExceptionConfiguration problem Cannot
- Caused by: java.lang.ClassNotFoundException: org.apache.shiro.spring.LifecycleBeanPostProcessor
- org.springframework.beans.factory.BeanDefinitionStoreException 与at org.springframework.asm.ClassRead
- 【SpringBoot】Spring Boot Configuration Annotation Processor not found in classpath
- spring - 4.2.0.RELEASE AsyncAnnotationBeanPostProcessor NoUniqueBeanDefinitionException
- How to load and execute Thread class when spring configuration loaded (如何在读取spring配置时自启动线程类)
- org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [/Users/lonecloud/tomcat/apache-tomcat-7.0.70 2/webapps/myproject/WEB-INF/classes/cn/lone
- Spring AutoConfigurationMetadataLoader是如何工作的 ?
- spring解析xml中的bean的一个关键类public class BeanDefinitionParserDelegate