学一学Spring中ConfigurationClassPostProcessor

Spring版本: 5.3.27

JDK版本: 1.8

一、概述

本文来看下Spring中BeanDefinitionRegistryPostProcessor唯一实现,BeanFactoryPostProcessor实现之一的ConfigurationClassPostProcessor

主要看下ConfigurationClassPostProcessor的作用,以及初探下BeanFactoryPostProcessor。

先上一张ConfigurationClassPostProcessor的类关系图:

BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor

这种接口继承接口的设计,个人理解是为了扩展功能。那为什么不把BeanDefinitionRegistryPostProcessor的功能直接写到BeanFactoryPostProcessor中呢?这个又涉及到职责分离的原则。

二、功能

1、BeanDefinitionRegistryPostProcessor

java 复制代码
 package org.springframework.beans.factory.support;
 ​
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
 ​
 /**
  * 源码注释翻译:
  * BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展,
  * 允许在常规的BeanFactoryPostProcessor介入之前注册更多的bean定义信息。
  * 特别是,BeanDefinitionRegistryPostProcessor可以注册bean定义信息,这些bean定义信息可能就是
  * 定义BeanFactoryPostProcessor实例的。
  */
 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
 ​
     /**
      * 源码注释翻译:
      * 在标准初始化之后修改应用程序上下文的内部bean定义注册中心(注意这里不是修改bean定义信息)。
      * 所有常规的bean定义信息都被加载,但是还没有被实例化。
      * 允许在下一个后置处理阶段介入前增加更多的bean定义信息。
      */
     void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
 ​
 }
 ​

2、BeanFactoryPostProcessor

java 复制代码
 package org.springframework.beans.factory.config;
 ​
 import org.springframework.beans.BeansException;
 ​
 /**
  * 源码注释翻译:
  * 允许自定义修改容器中bean定义信息的工厂钩子,调整容器中bean的属性值。
  *
  * 对于想通过自定义配置文件来覆盖容器中的bean属性来说非常有用。类似PropertyResourceConfigurer
  * 和其一些具体实现。
  *
  * BeanFactoryPostProcessor能够修改bean定义信息,但是不能实例化。
  * 如果实例化了,可能导致bean过早的实例化,破坏容器并导致意想不到的其他副作用。
  * 如果确实需要跟实例化的bean产生交互,可以考虑BeanPostProcessor。
  *
  * ApplicationContext自动侦测bean定义信息中的BeanFactoryPostProcessor类型的bean,并应用在其他bean被创建前。
  * BeanFactoryPostProcessor有可能被ConfigurableApplicationContext以编程方式进行注册。
  *
  * ApplicationContext中被自动侦测的BeanFactoryPostProcessor类型的bean会根据PriorityOrdered和Ordered被排序。
  * 与此形成鲜明对比的是,通过ConfigurableApplicationContext以编程方式注册的bean将按照注册的顺序应用; 
  * 任何通过实现PriorityOrdered或Ordered接口表达的顺序语义都会被编程注册的后处理器忽略。
  *
  */
 @FunctionalInterface
 public interface BeanFactoryPostProcessor {
 ​
     /**
      * 源码注释翻译:
      * 在标准初始化之后修改应用程序上下文的内部bean工厂。
      * 所有的bean定义信息都已经被加载,但是还没有实例化。
      * 甚至对于急切初始化的bean都可以覆盖和增加属性。
      */
     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
 ​
 }
 ​

三、源码分析

refresh方法中的invokeBeanFactoryPostProcessors方法

scss 复制代码
     package org.springframework.context.support;
     
     // ...省略部分代码
     final class PostProcessorRegistrationDelegate {
 ​
     // ...省略部分代码
 ​
     public static void invokeBeanFactoryPostProcessors(
             ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
 ​
         Set<String> processedBeans = new HashSet<>();
 ​
         if (beanFactory instanceof BeanDefinitionRegistry) {
             BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
             List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
             List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
 ​
             // 这里处理的就是通过编程方式注册的postProcessor
             // 如:context.addBeanFactoryPostProcessor
             // 可以看出这里没有对注册的postProcessor进行排序
             for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                     BeanDefinitionRegistryPostProcessor registryProcessor =
                             (BeanDefinitionRegistryPostProcessor) postProcessor;
                     registryProcessor.postProcessBeanDefinitionRegistry(registry);
                     registryProcessors.add(registryProcessor);
                 }
                 else {
                     regularPostProcessors.add(postProcessor);
                 }
             }
 ​
             List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
 ​
             // 1、调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors。
             String[] postProcessorNames =
                     beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
             for (String ppName : postProcessorNames) {
                 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                     processedBeans.add(ppName);
                 }
             }
             sortPostProcessors(currentRegistryProcessors, beanFactory);
             registryProcessors.addAll(currentRegistryProcessors);
             invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
             currentRegistryProcessors.clear();
 ​
             // 2、调用实现了Ordered的BeanDefinitionRegistryPostProcessors。
             postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
             for (String ppName : postProcessorNames) {
                 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                     processedBeans.add(ppName);
                 }
             }
             sortPostProcessors(currentRegistryProcessors, beanFactory);
             registryProcessors.addAll(currentRegistryProcessors);
             invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
             currentRegistryProcessors.clear();
 ​
             // 3、调用其他所有的BeanDefinitionRegistryPostProcessors,直到没有(这中间有可能会注册新的BeanDefinitionRegistryPostProcessors)
             boolean reiterate = true;
             while (reiterate) {
                 reiterate = false;
                 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                 for (String ppName : postProcessorNames) {
                     if (!processedBeans.contains(ppName)) {
                         currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                         processedBeans.add(ppName);
                         reiterate = true;
                     }
                 }
                 sortPostProcessors(currentRegistryProcessors, beanFactory);
                 registryProcessors.addAll(currentRegistryProcessors);
                 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
                 currentRegistryProcessors.clear();
             }
 ​
             // 调用截止目前所有的处理器的postProcessBeanFactory
             // 因为BeanDefinitionRegistryPostProcessor是继承了BeanFactoryPostProcessor的
             // 如果实现中有对beanFactory的修改,这里会进行处理。
             invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
             invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
         }
 ​
         else {
             // Invoke factory processors registered with the context instance.
             invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
         }
 ​
         String[] postProcessorNames =
                 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
 ​
         // 区分开实现了PriorityOrdered和Ordered以及剩下的BeanFactoryPostProcessor
         // 实现PriorityOrdered
     List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
         // 实现Ordered
         List<String> orderedPostProcessorNames = new ArrayList<>();
         // 剩下的
     List<String> nonOrderedPostProcessorNames = new ArrayList<>();
         for (String ppName : postProcessorNames) {
             if (processedBeans.contains(ppName)) {
                 // 跳过第一阶段已经处理过的
             }
             else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
             }
             else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                 orderedPostProcessorNames.add(ppName);
             }
             else {
                 nonOrderedPostProcessorNames.add(ppName);
             }
         }
 ​
         // 1, 调用实现了PriorityOrdered的BeanFactoryPostProcessor
         sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
         invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
 ​
         // 2, 调用实现了Ordered的BeanFactoryPostProcessor
         List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
         for (String postProcessorName : orderedPostProcessorNames) {
             orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
         }
         sortPostProcessors(orderedPostProcessors, beanFactory);
         invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
 ​
         // 3, 调用其他所有的BeanFactoryPostProcessors.
         List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
         for (String postProcessorName : nonOrderedPostProcessorNames) {
             nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
         }
         invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
 ​
         beanFactory.clearMetadataCache();
     }
     //...省略部分代码
     }

从上面对invokeBeanFactoryPostProcessors方法的分析可以看出,ConfigurationClassPostProcessor会在46及83行被处理。

46行:

invokeBeanDefinitionRegistryPostProcessors方法中会调用具体处理器的postProcessBeanDefinitionRegistry方法。

ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法会从配置类中分析出更多的bean定义信息注册到容器中。

83行

invokeBeanFactoryPostProcessors方法中会调用具体处理器的postProcessBeanFactory方法。

ConfigurationClassPostProcessor中的postProcessBeanFactory方法会将配置类通过CGLIB增强并替换原有的配置类,并在容器中新增了一个bean后置处理器。

四、自定义

java 复制代码
 package com.lazy.snail;
 ​
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 import org.springframework.core.PriorityOrdered;
 ​
 public class MyConfigPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
     @Override
     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
         System.out.println("我拿到了注册器,可以新增bean定义信息了");
     }
 ​
     @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
         System.out.println("容器在手,天下我有");
     }
 ​
     @Override
     public int getOrder() {
         return 0;
     }
 }
java 复制代码
 package com.lazy.snail;
 ​
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 ​
 @Slf4j
 public class SpringTest {
 ​
     @Test
     void test() {
         ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
         context.addBeanFactoryPostProcessor(new MyConfigPostProcessor());
         context.refresh();
     }
 }
 ​

五、小结

  • BeanFactoryPostProcessor 的职责

    • 主要针对已经存在的 BeanDefinition 进行修改,即:它在 Spring 容器启动时,BeanFactory 中所有的 Bean 定义信息已经加载进来之后,允许开发者通过 BeanFactoryPostProcessor 对这些 Bean 定义 进行修改或增强。
    • 例如,可以修改 Bean 的属性值、作用域等元数据,影响后续 Bean 的实例化过程。
  • BeanDefinitionRegistryPostProcessor 的职责

    • 主要是扩展 BeanDefinition 的注册阶段,它允许在 Spring 注册 Bean 定义信息之前 ,向容器中动态地 注册新的 Bean 定义信息 。它不仅能像 BeanFactoryPostProcessor 那样修改已经存在的 Bean 定义,还可以直接注册新的 BeanDefinition
    • 例如,可以通过实现 BeanDefinitionRegistryPostProcessor,动态地向 BeanDefinitionRegistry 中注册额外的 BeanDefinition,这通常用于一些框架级的扩展,比如 Spring Boot 的自动配置机制。
相关推荐
A_aspectJ1 小时前
‌Spring MVC的主要组件有哪些?
java·spring·mvc
Slow菜鸟2 小时前
Spring 设计模式之装饰器模式
spring·设计模式·装饰器模式
鹿屿二向箔3 小时前
【毕业论文+源码】基于SSM(Spring + Spring MVC + MyBatis)的房屋租赁系统
spring·mvc·mybatis
A_aspectJ4 小时前
Spring 框架中都用到了哪些设计模式?
spring·设计模式·1024程序员节
AIGC绘画4 小时前
Spring微服务概述之spring cloud alibaba服务调用实践
java·spring·微服务
带刺的坐椅5 小时前
Spring SPI、Solon SPI 有点儿像(Maven 与 Gradle)
java·spring·solon·spi
武昌库里写JAVA6 小时前
【MySql】-0.1、Unbunt20.04二进制方式安装Mysql5.7和8.0
spring boot·spring·毕业设计·layui·课程设计
鱼跃鹰飞10 小时前
大厂面试真题-简单描述一下SpringBoot的启动过程
java·spring boot·后端·spring·面试
尘浮生12 小时前
Java项目实战II基于Spring Boot的小型诊疗预约平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·spring·课程设计
Withered@12 小时前
Spring Boot面试题
spring boot·后端·spring