BeanDefinitionRegistryPostProcessor源码分析

2023年 10月 16日 121.5k 0

BeanDefinitionRegistryPostProcessor

  • BeanDefinitionRegistryPostProcessor
    • 一、基本信息
    • 二、接口描述
    • 三、接口源码
    • 四、主要功能
    • 五、最佳实践
    • 六、时序图
    • 七、源码分析
    • 八、注意事项
    • 九、总结
      • 最佳实践总结
      • 源码分析总结

一、基本信息

✒️ 作者 - Lex 📝 博客 - 我的CSDN 📚 文章目录 - 所有文章 🔗 源码地址 - BeanDefinitionRegistryPostProcessor源码

二、接口描述

BeanDefinitionRegistryPostProcessor 是 Spring 框架中的一个接口,它用于在 Spring 容器的标准初始化过程中允许我们修改应用程序上下文的内部 bean 定义。它继承自 BeanFactoryPostProcessor 接口。与 BeanFactoryPostProcessor 不同的是,它还提供了对 BeanDefinitionRegistry 的访问,这使得我们能够在运行时注册新的 beans 或修改现有的 bean 定义。

三、接口源码

InstantiationAwareBeanPostProcessor 是 Spring 框架自 3.0.1 版本开始引入的一个核心接口。最核心的方法是 postProcessBeanDefinitionRegistry,它允许我们在运行时注册新的 beans 或修改现有的 bean 定义。

/**
 * 相对于标准的 {@link BeanFactoryPostProcessor} SPI 的扩展,
 * 允许在常规 BeanFactoryPostProcessor 检测启动之前 注册更多的 bean 定义。
 * 特别地,BeanDefinitionRegistryPostProcessor 可以注册进一步的 bean 定义,
 * 这些定义可能会进一步定义 BeanFactoryPostProcessor 实例。
 *
 * 作者:Juergen Hoeller
 * 自版本:3.0.1 起
 * 参见:org.springframework.context.annotation.ConfigurationClassPostProcessor
 */
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * 在其标准初始化之后,修改应用上下文的内部 bean 定义注册表。
     * 此时,所有常规的 bean 定义都已经被加载,但还没有 bean 被实例化。
     * 这允许在下一后处理阶段开始之前,添加更多的 bean 定义。
     * 
     * @param registry 应用上下文使用的 bean 定义注册表
     * @throws org.springframework.beans.BeansException 如果发生错误
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

四、主要功能

  • 注册新的 Bean 定义

    • 该接口提供了一个机制,允许在 Spring 容器完成其标准初始化(即加载所有 bean 定义)之后,但在任何 bean 实例化之前,动态注册新的 bean 定义。
  • 修改现有的 Bean 定义

    • 除了能够添加新的 bean 定义,BeanDefinitionRegistryPostProcessor 还可以修改已经注册的 bean 定义。例如,它可以修改 bean 的属性值、构造函数参数或其它设置。
  • 控制 BeanFactoryPostProcessor 的执行顺序

    • 因为 BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的子接口,它的实现还可以控制 BeanFactoryPostProcessor 的执行顺序。这是因为在 Spring 容器启动时,所有的 BeanDefinitionRegistryPostProcessor beans 首先会被实例化和调用,然后才是其他的 BeanFactoryPostProcessor beans。
  • 基于条件的 Bean 注册

    • 可以利用 BeanDefinitionRegistryPostProcessor 来基于特定的运行时条件(例如类路径上是否存在某个特定的类)来决定是否注册某个 bean。
  • 扩展点以实现高级配置

    • 对于复杂的应用或框架,这个接口提供了一个扩展点,可以在初始化过程中进行更高级的配置,如加载外部的配置或执行特殊的验证逻辑。
  • 五、最佳实践

    首先来看看启动类入口,上下文环境使用AnnotationConfigApplicationContext(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个MyConfiguration组件类。然后我们从AnnotationConfigApplicationContext中获取MySimpleBean并调用show方法。

    public class BeanDefinitionRegistryPostProcessorApplication {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
            MySimpleBean mySimpleBean1 = context.getBean(MySimpleBean.class);
            mySimpleBean1.show();
        }
    }
    

    这里使用@Bean注解,为了确保 MyBeanDefinitionRegistryPostProcessor 被 Spring 容器执行,我们需要将它注册为一个 bean,该后处理器可以新增一个BeanDefinition

    @Configuration
    public class MyConfiguration {
    
        @Bean
        public static MyBeanDefinitionRegistryPostProcessor myBeanDefinitionRegistryPostProcessor(){
            return new MyBeanDefinitionRegistryPostProcessor();
        }
    }
    

    在我自定义的postProcessBeanDefinitionRegistry 方法中,创建了一个新的 RootBeanDefinition 对象,该对象代表 MySimpleBean 类。然后,使用了 registryregisterBeanDefinition 方法来注册这个新的 bean 定义,并为它指定了名称 "mySimpleBean"

    public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
        }
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            System.out.println("开始新增Bean定义");
            // 创建一个新的 BeanDefinition 对象
            BeanDefinition beanDefinition = new RootBeanDefinition(MySimpleBean.class);
            // 使用 registry 来注册这个新的 bean 定义
            registry.registerBeanDefinition("mySimpleBean", beanDefinition);
            System.out.println("完成新增Bean定义");
        }
    }
    

    要被动态注册的 Bean

    public class MySimpleBean {
    
        public void show() {
            System.out.println("MySimpleBean instance: " + this);
        }
    }
    

    运行结果发现,MySimpleBean 实例已成功创建,并打印了它的实例信息,这证明了 BeanDefinitionRegistryPostProcessor 成功地在运行时动态注册了这个 bean

    开始新增Bean定义
    完成新增Bean定义
    MySimpleBean instance: com.xcs.spring.config.MySimpleBean@7e5afaa6
    

    六、时序图

    sequenceDiagram
        Title: BeanFactoryPostProcessor时序图
        participant BeanDefinitionRegistryPostProcessorApplication
        participant AnnotationConfigApplicationContext
        participant AbstractApplicationContext
        participant PostProcessorRegistrationDelegate
        participant MyBeanDefinitionRegistryPostProcessor
        participant BeanDefinitionRegistry
        
        BeanDefinitionRegistryPostProcessorApplication->>AnnotationConfigApplicationContext:AnnotationConfigApplicationContext(...)启动上下文
        AnnotationConfigApplicationContext->>AbstractApplicationContext:refresh()
        AbstractApplicationContext->>AbstractApplicationContext:invokeBeanFactoryPostProcessors(...)触发整个BeanFactoryPostProcessor调用的流程
        AbstractApplicationContext->>PostProcessorRegistrationDelegate:invokeBeanFactoryPostProcessors(...)确保正确的顺序触发BeanDefinitionRegistryPostProcessor调用的流程
        PostProcessorRegistrationDelegate->>PostProcessorRegistrationDelegate:invokeBeanDefinitionRegistryPostProcessors(...)最终对BeanDefinitionRegistryPostProcessor接口回调
        PostProcessorRegistrationDelegate->>MyBeanDefinitionRegistryPostProcessor:postProcessBeanDefinitionRegistry(...)执行自定义的逻辑
        MyBeanDefinitionRegistryPostProcessor-->>BeanDefinitionRegistry:通过新增bean定义
        BeanDefinitionRegistry-->>MyBeanDefinitionRegistryPostProcessor:新增已完成
        PostProcessorRegistrationDelegate-->>AbstractApplicationContext: 调用Bean工厂后置处理器完成
        AnnotationConfigApplicationContext->>BeanDefinitionRegistryPostProcessorApplication:初始化完成
    

    七、源码分析

    首先来看看启动类入口,上下文环境使用AnnotationConfigApplicationContext(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个MyConfiguration组件类。然后我们从AnnotationConfigApplicationContext中获取MySimpleBean并调用show方法。

    public class BeanDefinitionRegistryPostProcessorApplication {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
            MySimpleBean mySimpleBean1 = context.getBean(MySimpleBean.class);
            mySimpleBean1.show();
        }
    }
    

    org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext构造函数中,执行了三个步骤,我们重点关注refresh()方法。

    public AnnotationConfigApplicationContext(Class... componentClasses) {
        this();
        register(componentClasses);
        refresh();
    }
    

    org.springframework.context.support.AbstractApplicationContext#refresh方法中,我们重点关注一下finishBeanFactoryInitialization(beanFactory)这方法会对实例化所有剩余非懒加载的单列Bean对象,其他方法不是本次源码阅读的重点暂时忽略。

    @Override
    public void refresh() throws BeansException, IllegalStateException {
         // ... [代码部分省略以简化]
         // 调用在上下文中注册为bean的工厂处理器
         invokeBeanFactoryPostProcessors(beanFactory);
         // ... [代码部分省略以简化]
    }
    

    org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中,又委托了PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()进行调用。

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
        // ... [代码部分省略以简化]
    }
    

    org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法中,主要是对BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor这两个接口的实现类进行回调,至于为什么这个方法里面代码很长呢?其实这个方法就做了一个事就是对处理器的执行顺序在做处理。比如说要先对实现了PriorityOrdered.class类回调,在对实现了Ordered.class类回调,最后才是对没有实现任何优先级的处理器进行回调。

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
    
        // 先调用 BeanDefinitionRegistryPostProcessors (如果有的话)
        Set processedBeans = new HashSet();
    
        // 判断 beanFactory 是否为 BeanDefinitionRegistry 的实例
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List regularPostProcessors = new ArrayList();
            List registryProcessors = new ArrayList();
    
            // 遍历所有的后处理器,按类型分类
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }
    
            // 这里不初始化 FactoryBeans,为了让 bean 工厂的后处理器可以应用到它们
            List currentRegistryProcessors = new ArrayList();
    
            // 首先,调用实现了 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();
    
            // 接下来,调用实现了 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();
    
            // 最后,调用所有其他的 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 回调
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }
    
        else {
            // 调用在上下文实例中注册的工厂处理器
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }
        
        // ... [代码部分省略以简化]
    }
    

    下面是我画的一个关于BeanDefinitionRegistryPostProcessor排序回调过程时序图大家可以参考一下。

    sequenceDiagram
        Title: BeanDefinitionRegistryPostProcessor回调排序时序图
        participant Init as invokeBeanFactoryPostProcessors
        participant BDRPP_PO as BDRPP(PriorityOrdered)
        participant BDRPP_O as BDRPP(Ordered)
        participant BDRPP as 其余的BDRPP
    
        Init->>BDRPP_PO: 回调
        BDRPP_PO-->>Init: 完成
        Init->>BDRPP_O: 回调
        BDRPP_O-->>Init: 完成
        Init->>BDRPP: 回调
        BDRPP-->>Init: 完成
        
        Note right of BDRPP: 提示: 
        Note right of BDRPP: BDRPP = BeanFactoryPostProcessor
    

    org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors方法中,循环调用了实现BeanDefinitionRegistryPostProcessor接口中的postProcessBeanDefinitionRegistry(registry)方法

    private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论