专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

spring源码 之 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor 是什么

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

可以看到该类继承了 BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 是什么,有什么用

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor

BeanFactoryPostProcessor 是什么,有什么用

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

上面的注释翻译下来大概意思是:可以参与应用上下文bena工厂初始化,所有的bean定义都被加载了,但是没有被实例化,允许我们去修改添加属性,甚至初始化bean(这个不懂,但是感觉一般都是用来修改已有的bean定义或者添加bean定义)

所以 ConfigurationClassPostProcessor 也有这个作用

什么时候执行

org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() {
    // 。。。 省略代码
    invokeBeanFactoryPostProcessors(beanFactory);
    //。。。 省略代码

}

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 获取自定义的 beanFactoyrPorcessor 并且 执行
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    //。。。 省略代码
}

先执行 postProcessBeanDefinitionRegistry

沃日 好复杂

1.ConfigurationClassPostProcessor#processConfigBeanDefinitions

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        // 获取所有已经在bean工厂的beandifition 名称
        String[] candidateNames = registry.getBeanDefinitionNames();
        //循环遍历beandifition名称
        for (String beanName : candidateNames) {
                //从bean工厂中获取beandifition
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            //判断这个beandefinition 是否被解析过,如果解析过,会往beandifition加一个标志
            //标志有两种,一种值为full,一种为lite 后面会说到
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                 // 去掉日志
            }
            //如果没有被解析过,会判断是否需要解析(下面讲)就往 configCandidates 添加
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        //。。。去掉判空和对 configCandidates 进行排序
        // 。。。去掉 BeanNameGenerator 和环境的生成
        // Parse each @Configuration class
        // 配置类解析,重要
        ConfigurationClassParser parser = new ConfigurationClassParser(...);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
           //重要,开始解析类
            parser.parse(candidates);
            //一些验证,没认真看 
            parser.validate();
            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);
            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(....);
            }
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
           //。。。 省略一些不影响主流程的代码,
        }
        while (!candidates.isEmpty());
         //。。。 省略一些不影响主流程的代码
    }

2.ConfigurationClassUtils.checkConfigurationClassCandidate

public static boolean checkConfigurationClassCandidate(
            BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
        String className = beanDef.getBeanClassName();
        //todo 这个不懂,为什么有 工厂方法就不解析? 
        if (className == null || beanDef.getFactoryMethodName() != null) {
            return false;
        }
        AnnotationMetadata metadata;
        // 。。。 去掉获取 metadata 的过程
        // 这个判读的方法 metadata.isAnnotated(Configuration.class.getName())
        //其实就判断是否注释了 @Configuration,如果有这个注释,那么设置参数值为
        // full
        if (isFullConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        //这个方法比较长,大概意思就是有没有 @Component @ComponentScan
        //@Import @ImportResource 这几个注解,方法是否有@Bean 这个注解
        //所以可以看出来这几个注解在 ConfigurationClassPostProcessor中都
        //被相应的解析,如果有就设置参数为lite
        else if (isLiteConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }
        else {
            return false;
        }
        //  用来设置order 排序
        Integer order = getOrder(metadata);
        if (order != null) {
            beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }
        return true;
    }

3.ConfigurationClassParser#parse 重点

public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    // 通过 bean的元信息进行解析
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                //......
            }
        }
            .......
    }

3.1.ConfigurationClassParser#processConfigurationClass

    protected final void parse(AnnotationMetadata metadata, String beanName) 
        processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }

protected void processConfigurationClass(ConfigurationClass configClass)  {
   // 检查是否要跳过 跟 @Conditional 有关,没认真看
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }
    //....省略无关主流程代码  
    // 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);
}

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) {
            //处理@Component 
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass);
        }
        // Process any @PropertySource annotations
        //处理 @PropertySources
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
            else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // Process any @ComponentScan annotations
        //  @ComponentScan 重要
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            for (AnnotationAttributes componentScan : componentScans) {
                // The config class is annotated with @ComponentScan -> perform the scan immediately
                // 这个很重要,解析 @ComponentScans 并且将解析出来的路径进行扫描
                //扫描得到的类,如果有@Compent等注解就注册到bean工厂中
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // Check the set of scanned definitions for any further config classes and parse recursively if needed
                // 这个是扫描出来的beandifition,进行迭代,防止还有@ComponentScans等注解需要解析
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // Process any @Import annotations 解析@Import 后面说
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        // Process any @ImportResource annotations
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        // Process individual @Bean methods
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        // Process default methods on interfaces
        processInterfaces(configClass, sourceClass);

        // Process superclass, if any
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") &&
                    !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // Superclass found, return its annotation metadata and recurse
                return sourceClass.getSuperClass();
            }
        }

        // No superclass -> processing is complete
        return null;
    }

3.1.1 @Import的解析

@Import()里面的value 可以放三种类 1.普通类 2.ImportSelector 3.ImportBeanDefinitionRegistrar 在ConfigurationClassParser#processImprots中解析


private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports) { //。。。省略无关主流程代码 else { this.importStack.push(configClass); try { for (SourceClass candidate : importCandidates) { if (candidate.isAssignable(ImportSelector.class)) { Class<?> candidateClass = candidate.loadClass(); //如果是ImportSelector 类,实例化 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); //如果是 DeferredImportSelector 就先放在 //deferredImportSelectors中,主要是是延迟加载,后面如果还记得就会说道哪里加载 if (selector instanceof DeferredImportSelector) { this.deferredImportSelectorHandler.handle( configClass, (DeferredImportSelector) selector); } else { //如果不是延迟加载的ImportSelectors,就调用 selectImports 方法,返回需要被bena工厂管理的bean全类名 String[] importClassNames = selector. selectImports (currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); //防止这些类有标志import,所以进行迭代 processImports(configClass, currentSourceClass, importSourceClasses, false); } } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // 如果是ImportBeanDefinitionRegistrar 就往 importBeanDefinitionRegistrars ,后面会集中对这个list进行你处理,主要是调用ImportBeanDefinitionRegistrar#registerBeanDefinitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); ParserStrategyUtils.invokeAwareMethods( registrar, this.environment, this.resourceLoader, this.registry); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // 这个是普通的类,有两种情况,一种ImportSelector返回的普通类,一种本来就是import的普通类,都会调用 processConfigurationClass方法进行递归处理,可能这些普通类有标志@CompentScans等注解需要解析处理 // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> // process it as an @Configuration class this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass)); } } } //。。。。。。 } }

……未完待续 还有好多 比如postProcessBeanFactory这个方法又干了好多事情

文章永久链接:https://tech.souyunku.com/26695

未经允许不得转载:搜云库技术团队 » spring源码 之 ConfigurationClassPostProcessor

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们