spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份

前言

  • 上篇博客spring 5.0.x源码学习系列五: AnnotationConfigApplicationContext类refresh方法之invokeBeanFactoryPostProcessor(一)主要解释的是invokeBeanFactoryPostProcessor方法的大致执行流程, 为了精通spring, 咱们除了要了解后置处理器的执行顺序外,还得明白这其中的一个特殊后置处理器(ConfigurationClassPostProcessor)的作用。下面将开始对ConfigurationClassPostProcessor的第一个重要的身份BeanDefinitionRegistryPostProcessor进行讲解(第二个身份BeanFactoryPostProcessor在下一篇博客进行总结)

一、ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份

  • 它的这个身份起到了非常重要的作用: 处理配置类并解析它们。 这句话可能有点难理解, 我们根据下面的篇幅慢慢理解。

二、流程图

  • 这里提供一张处理配置类流程图, 结合项目demo一起看


    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第1张图片
    在这里插入图片描述

三、项目demo

3.1 项目全景图

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第2张图片
在这里插入图片描述

3.1.1 EnableProxy类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第3张图片
在这里插入图片描述

3.1.2 ImportEugene类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第4张图片
在这里插入图片描述

3.1.3 UserDaoImpl类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第5张图片
在这里插入图片描述

3.1.4 ImportEugeneImportSelector类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第6张图片
在这里插入图片描述

3.1.5 MyImportBeanDefinitionRegistrar类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第7张图片
在这里插入图片描述

3.1.6 ImportEugeneBeanFactoryProcessor类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第8张图片
在这里插入图片描述

3.1.7 JDKProxyPostProcessor类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第9张图片
在这里插入图片描述

3.1.8 MyInvocationHandler类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第10张图片
在这里插入图片描述

3.1.9 ProxyUtil类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第11张图片
在这里插入图片描述

3.1.10 UserServiceImpl类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第12张图片
在这里插入图片描述

3.1.11 UserService类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第13张图片
在这里插入图片描述

3.1.12 AppConfig类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第14张图片
在这里插入图片描述

3.1.13 Entry类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第15张图片
在这里插入图片描述

3.1.14 TestBeanInAppConfig类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第16张图片
在这里插入图片描述

3.1.15 TestDaoInUserDaoImpl类

spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第17张图片
在这里插入图片描述

3.2 demo运行结果

  1. AppConfig存在@ImportEugene@EnableProxy注解时, 运行结果如下:

    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第18张图片
    在这里插入图片描述

    => 打印了7句 ========ImportEugene========的原因是有7个bean要创建, 分别为如下7个bean:AppConfig, UserServiceImpl, UserDaoImpl, ImportEugeneBeanFactoryProcessor, JDKProxyPostProcessor, TestBeanInAppConfig, TestDaoInUserDaoImpl

  2. AppConfig去除@ImportEugene@EnableProxy注解时, 运行结果如下:

    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第19张图片
    在这里插入图片描述

    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第20张图片
    在这里插入图片描述

    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第21张图片
    在这里插入图片描述

3.4 Demo运行结果总结

  • 本demo利用了spring的两个大扩展点: BeanPostProcessor@Import注解。其中自定义注解 @EnableProxy@ImportEugene利用了 @Import注解扩展点的两种类型: ImportSelectorImportBeanDefinitionRegistrar来实现

  • 关于上述的三个点BeanPostProcessor, ImportSelector, ImportSelector的功能将以如下表格来阐述

    扩展点 提供api 作用 使用示例
    BeanPostProcessor beanName和当前bean对象 可以动态修改bean 本案例中的为UserServiceImpl对象生成代理对象
    ImportSelector AnnotationMetadata 能获取到被导入的那个类的信息, 可以根据自定义的注解来动态写逻辑, 返回的字符串数组为类的全类名, spring会把他们当成bean去实例化 本案例中的ImportEugeneBeanFactoryProcessor, 动态的添加指定bean
    ImportBeanDefinitionRegistrar AnnotationMetadata和BeanDefinitionRegistry 拥有ImportSelector的api, 同时还能获取到BeanDefinitionRegister 本案例中的MyImportBeanDefinitionRegistrar, 动态的添加beanDefinition

四、运行原理

4.1 前言

  • 本demo中的演示只有几个部分和ConfigurationClassPostProcessor的BeanDefinitionRegistryPostProcessor身份有关, 只要涉及到bean的创建和bean的执行顺序, 都不属于本篇博客的内容, 添加一个demo演示是为了更好的说明问题, 现在开始总结原理

4.2 执行原理

4.2.1 在上篇博客中有总结到invokeBeanFactoryPostProcessors方法执行后置处理器的几个顺序。我们现在将从调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法开始

  1. postProcessBeanDefinitionRegistry方法源码

    @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);
    
        // 开始处理配置类, registry为bean工厂
        processConfigBeanDefinitions(registry);
    }
    
  2. processConfigBeanDefinitions处理配置类

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        // 存储配置类的数据结构: 很重要, 后续将解析此集合
        List configCandidates = new ArrayList<>();
    
        // 获取bean工厂的所有beanDefinition的名称, 在本次demo中, 一共有7个beanDefinition
        // 为spring内置的6个beanDefinition + AppConfig beanDefinition
        String[] candidateNames = registry.getBeanDefinitionNames();
    
        // 遍历beanDefinition
        for (String beanName : candidateNames) {
    
            // 根据beanName到bean工厂中拿到beanDefinition
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    
            // 判断是否为全注解或者部分注解  => 这里正常的spring流程下, 应该都没标注
            // 除非程序员自己利用扩展点修改了配置类对应的标识
            // eg: 标识它为全配置类
            // 配置类对应的beanDefinition.setAttribute(
            // "org.springframework.context.annotation.
            // ConfigurationClassPostProcessor.configurationClass", "full");
            // eg: 标识它为部分配置类
            // 配置类对应的beanDefinition.setAttribute(
            // "org.springframework.context.annotation.
            // ConfigurationClassPostProcessor.configurationClass", "lite");
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            // 正常情况下会走else, 
            // ConfigurationClassUtils.checkConfigurationClassCandidate的核心逻辑应该为如下代码
            // if (isFullConfigurationCandidate(metadata)) {
            //     beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
            // }
            // else if (isLiteConfigurationCandidate(metadata)) {
            //     beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
            // }
            // 若当前遍历的beanDefinition是一个配置类或者全配置类则给他一个标识, 并返回true
            // 进而将当前的beanDefinition添加到configCandidates数据结构中
            // 这里总结下什么叫全配置类什么叫部分配置类
            // 全配置类: 加了@Configuration注解
            // 部分配置类: 类中有@Component、@Import、@ImportResource、@ComponentScan注解及方法中有@Bean注解的类
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
    
        // Return immediately if no @Configuration classes were found
        // 若bean工厂中无配置类, 那么将结束解析配置类的流程
        if (configCandidates.isEmpty()) {
            return;
        }
    
        // Sort by previously determined @Order value, if applicable
        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 sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }
    
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
    
        // Parse each @Configuration class
        // 生成一个配置类的解析器, 将使用它来对配置类进行解析
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
        // 存放在解析配置类过程中得到的新的配置类, eg: 在解析@ComponentScan注解的扫描路径时,
        // 有可能扫描到其他的配置类
        Set candidates = new LinkedHashSet<>(configCandidates);
    
        // 将register方法中或者使用spring扩展点手动添加到bean工厂的配置类添加到存放解析完毕的数据结构中,
        // 为什么这么做? 因为后续将挨个去解析candidates的配置类, 并将新扫描出来或者import进去的
        // 配置类也添加到candidates里面去了, 不需要再解析一遍
        Set alreadyParsed = new HashSet<>(configCandidates.size());
    
        do {
            // 解析配置类, 执行到此, candidates中只有一个元素,
            // 因为在执行这个步骤的时候只有AppConfig对应的beanDefinition在bean工厂中
            parser.parse(candidates);
            parser.validate();
    
            // 拿到配置类解析器得到的配置类
            Set 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(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
    
            // 加载扫描出来的所有beanDefinition, 并在此将它们挨个注册到spring bean工厂中
            // 所以执行到这里时, configClasses中存储元素内容应该为:
            // 根据candidates中的配置类解析出来的所有配置类
            // (包括@Component注解的类、@Import注解导入的普通类、@Configuration的类)
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
    
            candidates.clear();
            // 这里还会校验这样一种情况,因为所有配置类是存到candidates变量中
            // 而上述this.reader.loadBeanDefinitions(configClasses);代码
            // 只是将配置类中导入的类注册到bean工厂中去,而此时有可能
            // 这些导入的类内部也会导入其他的类,所以还需要比较下当前解析的配置类
            // 中导入的类的数量和原来获取的配置类的数量。将多出来的配置类数量进行
            // 汇总,然后再统一处理它们
            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());
                }
                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();
        }
    }
    
  3. 解析器ConfigurationClassParser之parser方法

    public void parse(Set configCandidates) {
        this.deferredImportSelectors = new LinkedList<>();
    
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                // 这里会根据当前配置类的beanDefinition进入不同的解析逻辑,
                // 通过Register方法注册的beanDefinition类型统一为AnnotatedBeanDefinition
                // 这个在之前的博客中有总结过
                if (bd instanceof AnnotatedBeanDefinition) {
                    // 所以解析配置类的时候,是进入这个if分支
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
    
        processDeferredImportSelectors();
    }
    
  4. 解析器ConfigurationClassParser之processConfigurationClass方法 => 会将处理的当前配置类存入解析器的configurationClasses集合中

    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
    
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // Otherwise ignore new imported config class; existing non-imported class overrides it.
                return;
            }
            else {
                // Explicit bean definition found, probably replacing an import.
                // Let's remove the old one and go with the new one.
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }
    
        // Recursively process the configuration class and its superclass hierarchy.
        SourceClass sourceClass = asSourceClass(configClass);
        do {
            // 处理完当前配置类后, 会在方法中return null => 表示当前配置类被解析完成
            // 进而进入下面的逻辑, 将当前配置添加到configurationClasses中
            // 并在最外部
            // org.springframework.context.annotation.ConfigurationClassPostProcessor类
            // 中的processConfigBeanDefinitions方法中获取configurationClasses, 并
            // 解析它们(这里的解析不仅仅是注册beanDefinition, 还包括当前配置类中的
            // @Bean方法、@Import注解导入的类等等)
            sourceClass = doProcessConfigurationClass(configClass, sourceClass);
        }
        while (sourceClass != null);
    
        // 上面每次解析完配置类就添加到当前对象的configurationClasses属性中
        // 当前对象 => 就是在
        // org.springframework.context.annotation.ConfigurationClassPostProcessor类中
        // 的processConfigBeanDefinitions方法中创建出来的配置类解析器
        this.configurationClasses.put(configClass, configClass);
    }
    
  5. 解析器ConfigurationClassParser之doProcessConfigurationClass方法 => 处理@PropertySource, @ComponentScan, @Import, @ImportResource, @Bean注解

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
    
        // Recursively process any member (nested) classes first
        processMemberClasses(configClass, sourceClass);
    
        // Process any @PropertySource annotations
        // 处理@PropertySource注解, 没用过.....
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
            else {
                logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }
    
        // Process any @ComponentScan annotations
        // 处理@ComponentScan注解, sourceClass为当前解析的配置类, 即: AppConfig,
        Set 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
                // 扫描得到所有拥有@Component注解的beanDefinition, 并在
                // 内部(this.componentScanParser.parse)将它们注册到bean工厂
                Set scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // Check the set of scanned definitions for any further config classes and parse recursively if needed
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    // 在此校验扫描出来的@Component注解对应的beanDefinition, 因为有可能它们也被添加了配置类相关的注解,
                    // 所以也把它们当做配置类来解析
                    // 又因为@Component注解标识的类属于部分配置类, 所以肯定会将它们当做配置类再解析一遍
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        // 这里又调用了解析配置类逻辑, 递归调用
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
    
        // Process any @Import annotations
        // 处理当前配置类的@Import注解
        // 该方法的主要逻辑为如下:
        // 获取@Import注解的值, 并挨个遍历它们
    
        /*for (SourceClass candidate : importCandidates) {
    
            // 若导入的类是ImportSelector的类型
            if (candidate.isAssignable(ImportSelector.class)) {
                // Candidate class is an ImportSelector -> delegate to it to determine imports
                Class candidateClass = candidate.loadClass();
    
                // 使用反射创建对象, 为了调用ImportSelector的方法
                ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
    
                ParserStrategyUtils.invokeAwareMethods(
                        selector, this.environment, this.resourceLoader, this.registry);
    
                // 判断是否为延迟导入, 默认为null, 所有走else
                if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                    this.deferredImportSelectors.add(
                            new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                }
                else {
                    // 调用ImportSelector的selectImports方法, 得到返回的数组
                    String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                    // 将类对应的全路径转成Collection类型, 为了下面的递归调用
                    Collection importSourceClasses = asSourceClasses(importClassNames);
                    // 针对获取到的类的全路径, 把它们当做Import注解导入的类进行处理, 递归调用
                    processImports(configClass, currentSourceClass, importSourceClasses, false);
                }
            }
            // 处理类型为ImportBeanDefinitionRegistrar的类
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                // Candidate class is an ImportBeanDefinitionRegistrar ->
                // delegate to it to register additional bean definitions
                Class candidateClass = candidate.loadClass();
                // 使用反射创建对象
                ImportBeanDefinitionRegistrar registrar =
                        BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
    
                ParserStrategyUtils.invokeAwareMethods(
                        registrar, this.environment, this.resourceLoader, this.registry);
    
                // 将导入的ImportBeanDefinitionRegistrar类型的类添加到当前配置类存放ImportBeanDefinitionRegistrar
                // 类型的集合中, 方便后面处理配置类时能获取到它们
                configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
                // 非ImportSelector和ImportSelector的selectImports类型的类, 把它当成配置类处理
                // 在递归调用处理配置类逻辑processConfigurationClass
                // 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));
            }
        }*/
        processImports(configClass, sourceClass, getImports(sourceClass), true);
    
        // Process any @ImportResource annotations
        // 基于注解的方式的spring, 很少使用此注解, 所以这块没有总结到
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }
    
        // Process individual @Bean methods
        // 处理配置类中的方法存在@Bean注解的情况, 挨个遍历存放到当前配置类的数据结构中
        // 方便在外部处理配置类(loadBeanDefinition)时将它们获取出来
        Set 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;
    }
    
  6. 加载配置类之loadBeanDefinitions方法

    public void loadBeanDefinitions(Set configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        // 遍历传入的配置类集合
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
    
    
  7. 加载配置类之loadBeanDefinitionsForConfigurationClass方法

    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            String beanName = configClass.getBeanName();
            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                this.registry.removeBeanDefinition(beanName);
            }
            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
            return;
        }
    
        // 处理被@Import注解导入的普通类
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
    
        // 处理当前配置类中的所有@Bean标识的方法, 并将它注册到bean工厂
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }
    
        // 加载@ImportedResources注解导入的资源
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    
        // 将@Import注解导入的ImportBeanDefinitionRegistrar类型的bean注册到bean工厂
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
    

4.2.2 ConfigurationClassPostProcessor做为BeanDefinitionRegistryPostProcessor后置处理器的执行结果

  1. 执行结果和统计


    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第22张图片
    在这里插入图片描述

    spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份_第23张图片
    在这里插入图片描述
BeanDefinition Name 注册渠道
org.springframework.context.annotation.internalConfigurationAnnotationProcessor AnnotationConfigApplicationContext无参构造方法
org.springframework.context.event.internalEventListenerFactory AnnotationConfigApplicationContext无参构造方法
userServiceImpl 解析@ComponentScan注解
testDaoInUserDaoImpl @Bean注解
testDao AppConfig类的@Bean注解
org.springframework.context.event.internalEventListenerProcessor AnnotationConfigApplicationContext无参构造方法
org.springframework.context.annotation.internalAutowiredAnnotationProcessor AnnotationConfigApplicationContext无参构造方法
org.springframework.context.annotation.internalCommonAnnotationProcessor AnnotationConfigApplicationContext无参构造方法
appConfig register方法
userDaoImpl 解析@ComponentScan注解
JDKProxyPostProcessor 解析@Import注解
org.springframework.context.annotation.internalRequiredAnnotationProcessor AnnotationConfigApplicationContext无参构造方法
com.eugene.sumarry.csdn.invokeBeanFactoryPostProcessor2.postprocessor.ImportEugeneBeanFactoryProcessor 解析@Import注解

五、小结

5.1 黑箱理论

  • ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份的主要作用为:
        扫描并解析register方法注册的配置类, 解析完成后, 所有能被扫描出来的
        bean全部都以beanDefinition的形式存在于bean工厂中,为后续执行扫描
        出来的后置处理器和创建bean提供了条件
    

5.2 建议

  • 本篇博客提供的大多数为源码注释, 最好是能自己手动搭建与本次demo一样的项目结构, 结合提供的注释和运行结果一步一步的去了解ConfigurationClassPostProcessor作为BeanDefinitionRegistryPostProcessor身份的作用
  • I am a slow walker, but I never walk backwards.

你可能感兴趣的:(spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份)