Spring源码-11-后置处理器ConfigurationClassPostProcessor

Spring源码-11-后置处理器ConfigurationClassPostProcessor

Bean工厂后置处理器

一 类图

image

二 Demo

// MyTest00.java
public class MyTest00 {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("myCfg00", new RootBeanDefinition(MyCfg00.class));
        ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();
        postProcessor.postProcessBeanDefinitionRegistry(beanFactory);
    }
}
// MyCfg00.java
@Configuration
public class MyCfg00 {
}

三 BeanDefinitionRegistryPostProcessor抽象回调

// ConfigurationClassPostProcessor.java
@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);

        this.processConfigBeanDefinitions(registry);
    }
// ConfigurationClassPostProcessor.java
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        /**
         * 把配置类缓存起来
         * 配置类区分为
         *     - full型
         *         - @Configuration注解的proxyBeanMethods属性是true
         *     - lite型
         *         - @Configuration注解的proxyBeanMethods属性是false
         *         - 类上还有其他注解
         *             - @Component
         *             - @ComponentScan
         *             - @Import
         *             - @ImportResource
         *         - 类有@Bean标识的方法
         */
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames(); // 缓存在beanDefinitionNames中的名称

        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 缓存在beanDefinitionMap中的BeanDefinition
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 判定是full型配置类还是lite型配置类
                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 sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                        AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); // Bean名称生成器 配置类即将被封装成BeanDefinition放到Bean工厂 注册BeanDefinition时要指定名称
                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);

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // 配置类(full型和lite型)
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
            /**
             * 解析配置类
             *     - @Configuration标识的类封装成BeanDefinition注册到BeanFactory
             *     - @ComponentScan扫描的类封装成BeanDefinition注册到BeanFactory
             * @Import和@Bean注解的类不会封装成BeanDefinition
             */
            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注册进BeanFactory
             * @Import和@Bean注册的Bean在这一步被解析成BeanDefinition注册到Bean工厂
             */
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
            processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

            candidates.clear();
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = Set.of(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())) {
                            // 还没解析的类加到集合中轮询到下一个loop中
                            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());
        }

        // Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
        this.propertySourceDescriptors = parser.getPropertySourceDescriptors();

        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory 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.clearCache();
        }
    }

1 配置类解析

配置类解析传送门

2 BeanDefinition注册Bean工厂

上面parse(...)阶段

  • 可能发生BeanDefinition注册Bean工厂

  • 可能在配置类中缓存了

    • importBeanDefinitionRegistrars
      • @Import注解导入了实现了ImportBeanDefinitionRegistrar的类
    • imports
      • @Import注解导入的类(没有实现ImportSelector接口和ImportBeanDefinitionRegistrar接口)
    • importedResources
      • @ImportResource导入的配置文件
    • beanMethods
      • @Bean标识的方法
// ConfigurationClassPostProcessor.java
/**
             * 上面parse(...)阶段
             *     - 可能发生BeanDefinition注册Bean工厂
             *     - 可能在配置类中缓存了
             *         - importBeanDefinitionRegistrars
             *             - @Import注解导入了实现了ImportBeanDefinitionRegistrar的类
             *         - imports
             *             - @Import注解导入的类(没有实现ImportSelector接口和ImportBeanDefinitionRegistrar接口)
             *         - importedResources
             *             - @ImportResource导入的配置文件
             *         - beanMethods
             *             - @Bean标识的方法
             *
             */
            this.reader.loadBeanDefinitions(configClasses);
// ConfigurationClassBeanDefinitionReader.java
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
// ConfigurationClassBeanDefinitionReader.java
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;
        }

        if (configClass.isImported()) { // 配置类是被@Import进来的
            registerBeanDefinitionForImportedConfigurationClass(configClass); // 导入进来的类是个配置类 封装成BeanDefinition注册Bean工厂
        }
        for (BeanMethod beanMethod : configClass.getBeanMethods()) { // 缓存着@Bean方法
            loadBeanDefinitionsForBeanMethod(beanMethod); // @Bean注解的方法 方法返回值类型的类封装成BeanDefinition注册Bean工厂
        }

        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); // @ImportResource导入的配置文件
        // @Import注册的Bean实现了ImportBeanDefinitionRegistrar 回调这个接口的registerBeanDefinitions方法
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }

四 BeanFactoryPostProcessor抽象回调

// ConfigurationClassPostProcessor.java
@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);
        }
        /**
         * Bean工厂后置处理器
         *     - 超类 BeanFactoryPostProcessor回调postProcessBeanFactory方法
         *     - 子类 BeanDefinitionRegistryPostProcessor回调postProcessBeanDefinitionRegistry
         * 两个两调中都会处理配置类
         * 避免重复执行通过id进行标识后置处理器是否已经处理过配置类
         */
        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);
        }

        /**
         * beanFactory实现是DefaultListableBeanFactory
         * @Configuration(proxyBeanMethods=true)标识的full型配置类的Bean类进行增强
         *     - 这个时候还没发生Bean实例化/初始化
         *     - 仅仅是将BeanDefinition已经注册在了Bean工厂中
         *     - 此时将BeanDefinition中Bean的Class进行增强
         *     - 将来进行实例化时回调
         */
        this.enhanceConfigurationClasses(beanFactory);
        // 向Bean工厂注册一个Bean后置处理器
        beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }

1 full型配置类增强

传送门

2 Bean后置处理器注册

传送门

3 Bean后置处理器ImportAwareBeanPostProcessor

传送门

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容