关于java:spring-50x源码学习系列六-后置处理器BeanDefinitionRegistryPostProcessor身份

3次阅读

共计 19517 个字符,预计需要花费 49 分钟才能阅读完成。

前言

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

一、ConfigurationClassPostProcessor 之 BeanDefinitionRegistryPostProcessor 身份

  • 它的这个身份起到了十分重要的作用: 解决配置类并解析它们。这句话可能有点难了解, 咱们依据上面的篇幅缓缓了解。

二、流程图

  • 这里提供一张解决配置类流程图, 联合我的项目 demo 一起看

三、我的项目 demo

3.1 我的项目全景图

3.1.1 EnableProxy 类

3.1.2 ImportEugene 类

3.1.3 UserDaoImpl 类

3.1.4 ImportEugeneImportSelector 类

3.1.5 MyImportBeanDefinitionRegistrar 类

3.1.6 ImportEugeneBeanFactoryProcessor 类

3.1.7 JDKProxyPostProcessor 类

3.1.8 MyInvocationHandler 类

3.1.9 ProxyUtil 类

3.1.10 UserServiceImpl 类

3.1.11 UserService 类

3.1.12 AppConfig 类

3.1.13 Entry 类

3.1.14 TestBeanInAppConfig 类

3.1.15 TestDaoInUserDaoImpl 类

3.2 demo 运行后果

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

    => 打印了 7 句 ========ImportEugene========的起因是有 7 个 bean 要创立, 别离为如下 7 个 bean:AppConfig, UserServiceImpl, UserDaoImpl, ImportEugeneBeanFactoryProcessor, JDKProxyPostProcessor, TestBeanInAppConfig, TestDaoInUserDaoImpl
  2. AppConfig 去除 @ImportEugene@EnableProxy注解时, 运行后果如下:


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<BeanDefinitionHolder> 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<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    
        // 将 register 办法中或者应用 spring 扩大点手动增加到 bean 工厂的配置类增加到寄存解析结束的数据结构中,
        // 为什么这么做?因为后续将挨个去解析 candidates 的配置类, 并将新扫描进去或者 import 进去的
        // 配置类也增加到 candidates 外面去了, 不须要再解析一遍
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    
        do {
            // 解析配置类, 执行到此, candidates 中只有一个元素,
            // 因为在执行这个步骤的时候只有 AppConfig 对应的 beanDefinition 在 bean 工厂中
            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(
                        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<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> 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<BeanDefinitionHolder> 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<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
                // 扫描失去所有领有 @Component 注解的 beanDefinition, 并在
                // 外部 (this.componentScanParser.parse) 将它们注册到 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
                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<SourceClass> 类型, 为了上面的递归调用
                    Collection<SourceClass> 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<? extends BeanDefinitionReader> 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<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;
    }
  6. 加载配置类之 loadBeanDefinitions 办法

    public void loadBeanDefinitions(Set<ConfigurationClass> 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. 执行后果和统计

![在这里插入图片形容](https://img-blog.csdnimg.cn/20200108105148448.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2F2ZW5nZXJFdWc=,size_16,color_FFFFFF,t_70)
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.
正文完
 0