ConfigurationClassPostProcessor自动装配流程图解

发布时间:2023-09-28 10:30

        ConfigurationClassPostProcessor是Spring中自动装配最核心的类,通过分析各个类的信息封装成BeanDifinition,他是一个后置处理器的类,如果弄懂了ConfigurationClassPostProcessor的处理方式,那么Spring和Spring Boot的装配逻辑也就明白了,此类中有很多递归调用,考虑了很多场景,所以流程图中流程之间的联系较为负责,但是当你看懂了全局以后,无法就是递归、再递归,不放过任何可能。

主要功能如下

1、解析@Configuration的配置类

2、解析@ComponentScan扫描的包

3、解析@ComponentScans扫描的包

4、解析@Import注解

5、解析@Component注解,包含继承了@Component的注解

6、解析@ImportResource

7、解析@Bean

.......

1、能力有限,图有点丑

2、下面是图片,但是在这里持续完善

这里整个类加了注释的代码

/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the \"License\");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an \"AS IS\" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.annotation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
import org.springframework.beans.factory.parsing.PassThroughSourceExtractor;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * 此类是一个后置处理器的类,主要功能是参与BeanFactory的建造,主要功能如下
 *   1、解析加了@Configuration的配置类
 *   2、解析@ComponentScan扫描的包
 *   3、解析@ComponentScans扫描的包
 *   4、解析@Import注解
 *
 * {@link BeanFactoryPostProcessor} used for bootstrapping processing of
 * {@link Configuration @Configuration} classes.
 *
 * 

Registered by default when using {@code } or * {@code }. Otherwise, may be declared manually as * with any other BeanFactoryPostProcessor. * *

This post processor is priority-ordered as it is important that any * {@link Bean} methods declared in {@code @Configuration} classes have * their corresponding bean definitions registered before any other * {@link BeanFactoryPostProcessor} executes. * * @author Chris Beams * @author Juergen Hoeller * @author Phillip Webb * @since 3.0 */ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { /** * 使用类的全限定名作为bean的默认生成策略 * * A {@code BeanNameGenerator} using fully qualified class names as default bean names. *

This default for configuration-level import purposes may be overridden through * {@link #setBeanNameGenerator}. Note that the default for component scanning purposes * is a plain {@link AnnotationBeanNameGenerator#INSTANCE}, unless overridden through * {@link #setBeanNameGenerator} with a unified user-level bean name generator. * @since 5.2 * @see #setBeanNameGenerator */ public static final AnnotationBeanNameGenerator IMPORT_BEAN_NAME_GENERATOR = new FullyQualifiedAnnotationBeanNameGenerator(); private static final String IMPORT_REGISTRY_BEAN_NAME = ConfigurationClassPostProcessor.class.getName() + \".importRegistry\"; private final Log logger = LogFactory.getLog(getClass()); private SourceExtractor sourceExtractor = new PassThroughSourceExtractor(); private ProblemReporter problemReporter = new FailFastProblemReporter(); @Nullable private Environment environment; private ResourceLoader resourceLoader = new DefaultResourceLoader(); @Nullable private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(); private boolean setMetadataReaderFactoryCalled = false; private final Set registriesPostProcessed = new HashSet<>(); private final Set factoriesPostProcessed = new HashSet<>(); @Nullable private ConfigurationClassBeanDefinitionReader reader; // 是否使用本地xml配置的beanNameGenerator生成器 private boolean localBeanNameGeneratorSet = false; /* Using short class names as default bean names by default. */ // 使用短类名作为bean名称生成策略 private BeanNameGenerator componentScanBeanNameGenerator = AnnotationBeanNameGenerator.INSTANCE; /* Using fully qualified class names as default bean names by default. */ // 使用类的全限定名作为bean默认生成策略 private BeanNameGenerator importBeanNameGenerator = IMPORT_BEAN_NAME_GENERATOR; @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE; // within PriorityOrdered } /** * Set the {@link SourceExtractor} to use for generated bean definitions * that correspond to {@link Bean} factory methods. */ public void setSourceExtractor(@Nullable SourceExtractor sourceExtractor) { this.sourceExtractor = (sourceExtractor != null ? sourceExtractor : new PassThroughSourceExtractor()); } /** * Set the {@link ProblemReporter} to use. *

Used to register any problems detected with {@link Configuration} or {@link Bean} * declarations. For instance, an @Bean method marked as {@code final} is illegal * and would be reported as a problem. Defaults to {@link FailFastProblemReporter}. */ public void setProblemReporter(@Nullable ProblemReporter problemReporter) { this.problemReporter = (problemReporter != null ? problemReporter : new FailFastProblemReporter()); } /** * Set the {@link MetadataReaderFactory} to use. *

Default is a {@link CachingMetadataReaderFactory} for the specified * {@linkplain #setBeanClassLoader bean class loader}. */ public void setMetadataReaderFactory(MetadataReaderFactory metadataReaderFactory) { Assert.notNull(metadataReaderFactory, \"MetadataReaderFactory must not be null\"); this.metadataReaderFactory = metadataReaderFactory; this.setMetadataReaderFactoryCalled = true; } /** * Set the {@link BeanNameGenerator} to be used when triggering component scanning * from {@link Configuration} classes and when registering {@link Import}\'ed * configuration classes. The default is a standard {@link AnnotationBeanNameGenerator} * for scanned components (compatible with the default in {@link ClassPathBeanDefinitionScanner}) * and a variant thereof for imported configuration classes (using unique fully-qualified * class names instead of standard component overriding). *

Note that this strategy does not apply to {@link Bean} methods. *

This setter is typically only appropriate when configuring the post-processor as a * standalone bean definition in XML, e.g. not using the dedicated {@code AnnotationConfig*} * application contexts or the {@code } element. Any bean name * generator specified against the application context will take precedence over any set here. * @since 3.1.1 * @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator) * @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR */ public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { Assert.notNull(beanNameGenerator, \"BeanNameGenerator must not be null\"); this.localBeanNameGeneratorSet = true; this.componentScanBeanNameGenerator = beanNameGenerator; this.importBeanNameGenerator = beanNameGenerator; } @Override public void setEnvironment(Environment environment) { Assert.notNull(environment, \"Environment must not be null\"); this.environment = environment; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { Assert.notNull(resourceLoader, \"ResourceLoader must not be null\"); this.resourceLoader = resourceLoader; if (!this.setMetadataReaderFactoryCalled) { this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader); } } @Override public void setBeanClassLoader(ClassLoader beanClassLoader) { this.beanClassLoader = beanClassLoader; if (!this.setMetadataReaderFactoryCalled) { this.metadataReaderFactory = new CachingMetadataReaderFactory(beanClassLoader); } } /** * 定位、加载、解析、注册相关注解 * * Derive further bean definitions from the configuration classes in the registry. */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常 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); } // 将马上要进行处理的registry对象的id值放到已经处理的集合对象中 this.registriesPostProcessed.add(registryId); // 处理配置类的bean定义信息 processConfigBeanDefinitions(registry); } /** * 添加CGLIB增强处理及ImportAwareBeanPostProcessor后置处理类 * * Prepare the Configuration classes for servicing bean requests at runtime * by replacing them with CGLIB-enhanced subclasses. */ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( \"postProcessBeanFactory already called on this post-processor against \" + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); } /** * 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作 * * 如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了 * * Build and validate a configuration model based on the registry of * {@link Configuration} classes. */ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // 创建存放BeanDefinitionHolder的对象集合 List configCandidates = new ArrayList<>(); // 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName String[] candidateNames = registry.getBeanDefinitionNames(); // 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的) for (String beanName : candidateNames) { // 获取指定名称的BeanDefinition对象 BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息 if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug(\"Bean definition has already been processed as a configuration class: \" + beanDef); } } // 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用 // 如果Configuration配置proxyBeanMethods代理为true则为full // 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite // 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 添加到对应的集合对象中 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 // 如果适用,则按照先前确定的@Order的值排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context // 判断当前类型是否是SingletonBeanRegistry类型 SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { // 类型的强制转换 sbr = (SingletonBeanRegistry) registry; // 判断是否有自定义的beanName生成器 if (!this.localBeanNameGeneratorSet) { // 获取自定义的beanName生成器 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); // 如果有自定义的命名生成策略 if (generator != null) { //设置组件扫描的beanName生成策略 this.componentScanBeanNameGenerator = generator; // 设置import bean name生成策略 this.importBeanNameGenerator = generator; } } } // 如果环境对象等于空,那么就重新创建新的环境对象 if (this.environment == null) { this.environment = new StandardEnvironment(); } // Parse each @Configuration class // 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 创建两个集合对象, // 存放相关的BeanDefinitionHolder对象 Set candidates = new LinkedHashSet<>(configCandidates); // 存放扫描包下的所有bean Set alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition parser.parse(candidates); // 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB parser.validate(); // 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象 Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); // 清除掉已经解析处理过的配置类 configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content // 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器 if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器 this.reader.loadBeanDefinitions(configClasses); // 添加到已经处理的集合中 alreadyParsed.addAll(configClasses); candidates.clear(); // 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition // 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean) // 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析 // 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了 if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } // 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中 for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { 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 && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it\'ll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } } /** * Post-processes a BeanFactory in search of Configuration class BeanDefinitions; * any candidates are then enhanced by a {@link ConfigurationClassEnhancer}. * Candidate status is determined by BeanDefinition attribute metadata. * @see ConfigurationClassEnhancer */ public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); MethodMetadata methodMetadata = null; if (beanDef instanceof AnnotatedBeanDefinition) { methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); } if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived @Bean method // -> resolve bean class at this point... AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef; if (!abd.hasBeanClass()) { try { abd.resolveBeanClass(this.beanClassLoader); } catch (Throwable ex) { throw new IllegalStateException( \"Cannot load configuration class: \" + beanDef.getBeanClassName(), ex); } } } if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) { if (!(beanDef instanceof AbstractBeanDefinition)) { throw new BeanDefinitionStoreException(\"Cannot enhance @Configuration bean definition \'\" + beanName + \"\' since it is not stored in an AbstractBeanDefinition subclass\"); } else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { logger.info(\"Cannot enhance @Configuration bean definition \'\" + beanName + \"\' since its singleton instance has been created too early. The typical cause \" + \"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor \" + \"return type: Consider declaring such methods as \'static\'.\"); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // Set enhanced subclass of the user-specified bean class Class configClass = beanDef.getBeanClass(); Class enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass != enhancedClass) { if (logger.isTraceEnabled()) { logger.trace(String.format(\"Replacing bean definition \'%s\' existing class \'%s\' with \" + \"enhanced class \'%s\'\", entry.getKey(), configClass.getName(), enhancedClass.getName())); } beanDef.setBeanClass(enhancedClass); } } } private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { private final BeanFactory beanFactory; public ImportAwareBeanPostProcessor(BeanFactory beanFactory) { this.beanFactory = beanFactory; } /** * 如果配置类有Configuration注解,会进行动态代理,会实现EnhancedConfiguration接口,里面有个setBeanFactory接口方法,会传入beanFactory * @param pvs * @param bean * @param beanName * @return */ @Override public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) { // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor\'s // postProcessProperties method attempts to autowire other configuration beans. if (bean instanceof EnhancedConfiguration) { ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory); } return pvs; } /** * 如果是ImportAware类型的,就会设置bean的注解信息 * @param bean * @param beanName * @return */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { if (bean instanceof ImportAware) { ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class); AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName()); if (importingClass != null) { ((ImportAware) bean).setImportMetadata(importingClass); } } return bean; } } }

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号