学一学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 的自动配置机制。
相关推荐
有梦想的攻城狮6 小时前
spring中的@MapperScan注解详解
java·后端·spring·mapperscan
柚个朵朵7 小时前
Spring的Validation,这是一套基于注解的权限校验框架
java·后端·spring
程序员小杰@7 小时前
【MCP教程系列】SpringBoot 搭建基于 Spring AI 的 SSE 模式 MCP 服务
人工智能·spring boot·spring
程序员buddha7 小时前
Spring & Spring Boot 常用注解整理
java·spring boot·spring
C_V_Better8 小时前
Java Spring Boot 控制器中处理用户数据详解
java·开发语言·spring boot·后端·spring
LUCIAZZZ9 小时前
JVM之虚拟机运行
java·jvm·spring·操作系统·springboot
神秘的t10 小时前
Spring Web MVC————入门(2)
java·spring·mvc
冷心笑看丽美人10 小时前
Spring MVC数据绑定和响应 你了解多少?
java·spring·mvc
蒂法就是我14 小时前
详细说说Spring的IOC机制
java·后端·spring
唐僧洗头爱飘柔952715 小时前
【SSM-SpringMVC(二)】Spring接入Web环境!本篇开始研究SpringMVC的使用!SpringMVC数据响应和获取请求数据
java·spring·文件上传·页面跳转·数据响应·获取请求数据·静态资源访问