美文网首页
ConfigurationClassPostProcessor

ConfigurationClassPostProcessor

作者: rock_fish | 来源:发表于2019-12-06 17:08 被阅读0次

传送:

Spring大观园,我有过的困惑或许你也有!


导读

1.是谁在何时注册了ConfigurationClassPostProcessor ?
2.是谁在何时调用ConfigurationClassPostProcessor?
3.ConfigurationClassPostProcessor的作用

1.是谁在何时注册了ConfigurationClassPostProcessor
  1. AnnotationConfigApplicationContext 构造函数中创建了AnnotatedBeanDefinitionReader。
  2. AnnotatedBeanDefinitionReader 的构造函数中注册注解配置类的处理器,其中有ConfigurationClassPostProcessor。
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

跟进源码查看,可见

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // 在这里注册了ConfigurationClassPostProcessor类。
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            // 调用registerPostProcessor来进行注册
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
2.是谁在何时调用ConfigurationClassPostProcessor?

笔记invokeBeanFactoryPostProcessors源码分析中,可以快速找到答案

3.ConfigurationClassPostProcessor的作用(本篇重点)
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 开始注册Config类中定义的BeanDefinition
        processConfigBeanDefinitions(registry);
    }

筛选代码来梳理,有3个关键逻辑
1.筛选出候选配置类
2.解析配置类 parser.parse(candidates)
3.加载配置类中引入的BeanDefinition this.reader.loadBeanDefinitions(configClasses);

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();
        // 将配置类放在configCandidates列表中。部分代码省略...
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                        //被处理过的配置类的定义中,会被打Full、Lite属性标记。
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
                        //筛选出配置类,放置到configCandidates(配置候选者)中
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
       

        // 创建配置类的分析器,对配置类进行分析。配置类就是我们添加了@Configuration注解的类,可以有多个的,通常springboot项目中是启动类
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        do {
            // 开始分析配置类
            parser.parse(candidates);
            parser.validate();

            // 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
            this.reader.loadBeanDefinitions(configClasses);
        }
        while (!candidates.isEmpty());
    }
  1. 配置类的判断ConfigurationClassUtils.checkConfigurationClassCandidateFullLite 后边在说

  2. parser.parse(candidates) 跟踪到关键方法processConfigurationClass

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {   

        // 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);
    }

细节可以查看,跟着节奏自己捋一遍源码配置类解析源码解析-脑图版

相关文章

网友评论

      本文标题:ConfigurationClassPostProcessor

      本文链接:https://www.haomeiwen.com/subject/pisegctx.html