学一学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 的自动配置机制。
相关推荐
壹佰大多1 小时前
【spring-cloud-gateway总结】
java·spring·gateway
CodeChampion1 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
秋意钟1 小时前
Spring框架处理时间类型格式
java·后端·spring
科马5 小时前
【Redis】缓存
数据库·redis·spring·缓存
cloud___fly5 小时前
Spring AOP入门
java·后端·spring
zxguan8 小时前
Springboot 学习 之 logback-spring.xml 日志压缩 .tmp 临时文件问题
spring boot·学习·spring
繁川8 小时前
深入理解Spring AOP
java·后端·spring
AI人H哥会Java15 小时前
【Spring】Spring的模块架构与生态圈—Spring MVC与Spring WebFlux
java·开发语言·后端·spring·架构
小马爱打代码16 小时前
SpringCloud(注册中心+OpenFeign+网关+配置中心+服务保护+分布式事务)
分布式·spring·spring cloud
Watermelon_Mr16 小时前
Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器
java·后端·spring