Spring 源码学习 11:invokeBeanFactoryPostProcessors

简介: 通过以上的阅读,对 invokeBeanFactoryPostProcessors(beanFactory); 这一步方法进行总结。

前言


invokeBeanFactoryPostProcessors 会执行 BeanFactory 的后置处理器。看到这里会有疑问:

  1. 什么是 BeanFactoryPostProcessor ?
  2. BeanfactoryPostProcessor 该如何使用?

知道了上面两个问题的答案,对 BeanFactoryPostProcessor 有了了解之后,然后再深入源码,继续阅读 invokeBeanFactoryPostProcessors 这个方法。


作用


资料还是在官网可以找到答案:

网络异常,图片无法展示
|

阅读了一下,大概意思是 Spring IoC 容器允许 BeanFactoryPostProcessor 读取配置元数据,并有可能在容器实例化除 BeanFactoryPostProcessor 实例以外的任何 bean 之前更改它。

同样可以使用 Ordered 接口对 BeanFactoryPostProcessor 进行排序。


注意


网络异常,图片无法展示
|

BeanFactoryPostProcessor 操作的是 BeanDefinition ,即元数据。但是同样可以通过获取到 BeanFactory 进行实例化 Bean,但是官网很不建议这样使用。


示例

使用 BeanFactoryPostProcessor

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 修改 BeanDefinition 信息
        BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
        userComponentBeanDefinition.setLazyInit(true);
        // 修改 Bean 的信息
        // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean
        UserComponent bean = beanFactory.getBean(UserComponent.class);
        bean.setUserName("liuzhihang-01");
    }
}


创建自己的 BeanFactoryPostProcessor 并实现 BeanFactoryPostProcessor 接口,添加注解即可。

网络异常,图片无法展示
|


当然除了实现 BeanFactoryPostProcessor 接口,还有其他接口可以实现:

网络异常,图片无法展示
|


使用 BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,同时扩展了增加了 postProcessBeanDefinitionRegistry 方法。可以支持在 BeanDefinition 注册之后 Bean 实例化之前对 BeanDefinition 进行操作。

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 修改 BeanDefinition 信息
        BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
        userComponentBeanDefinition.setLazyInit(true);
        // 修改 Bean 的信息
        // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean
        UserComponent bean = beanFactory.getBean(UserComponent.class);
        bean.setUserName("liuzhihang-01");
    }
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 注册一个 BeanDefinition
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(OrderComponent.class);
        AbstractBeanDefinition orderComponentBeanDefinition = builder.getBeanDefinition();
        registry.registerBeanDefinition("orderComponent", orderComponentBeanDefinition);
    }
}


下面是测试代码截图:

网络异常,图片无法展示
|

OrderComponent 类没有添加任何注解,然后注册为 BeanDefinition 之后,从容器中可以获取到 orderComponent。


如何修改字段属性

在 Spring 文档上说明,非常不建议在 BeanFactoryPostProcessor 中实例化 Bean,那这时候想修改 Bean 的信息,改如何操作?

其实可以通过获取到 MutablePropertyValues 后进行操作:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 修改 BeanDefinition 信息
        BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
        userComponentBeanDefinition.setLazyInit(true);
        MutablePropertyValues userComponentPropertyValues = userComponentBeanDefinition.getPropertyValues();
        userComponentPropertyValues.addPropertyValue("userName", "liuzhihang-02");
        // 修改 Bean 的信息
        // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean
        // UserComponent bean = beanFactory.getBean(UserComponent.class);
        // bean.setUserName("liuzhihang-01");
    }
}


invokeBeanFactoryPostProcessors

看完前面,我想已经知道了 BeanFactoryPostProcessor 是做什么用的了,而这一步的主要作用就是实例化所有的 BeanFactoryPostProcessor。

进入源码:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}


其中 getBeanFactoryPostProcessors 方法获取的是自己添加的 BeanFactoryPostProcessor。这句话是什么意思呢?

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}


看源码,就是直接从 beanFactoryPostProcessors 获取的,那如何向其中添加呢?

网络异常,图片无法展示
|


其实调用容器的 addBeanFactoryPostProcessor 方法即可。

继续阅读重点代码 invokeBeanFactoryPostProcessors

注意注意,这块代码非常长!

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();
    // 判断是否为 BeanDefinitionRegistry
    // debug 发现 这里传入的是 DefaultListableBeanFactory
    // DefaultListableBeanFactory 实现了 BeanDefinitionRegistry
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 创建了两个 List 集合, 用来存放处理器
        // BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口
        // BeanDefinitionRegistryPostProcessor 还可以额外处理 BeanDefinition, 添加 BeanDefinition
        // 用法可以参考示例
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        // 循环 beanFactoryPostProcessors
        // beanFactoryPostProcessors 是使用 API context.addBeanFactoryPostProcessor 添加进来的
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // BeanDefinitionRegistryPostProcessor 要单独添加到 registryProcessors
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 处理 Bean 的信息
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            } else {
                regularPostProcessors.add(postProcessor);
            }
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        // 上面循环是执行的我们调用 API 添加的 BeanDefinitionRegistryPostProcessor
        // 下面执行 Spring 自己的 BeanDefinitionRegistryPostProcessor 集合
        // 先执行实现了 PriorityOrdered接口的,然后是 Ordered 接口的,最后执行剩下的
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 第一步先调用 BeanDefinitionRegistryPostProcessors 它实现了PriorityOrdered
        // 在初始化 reader 时 在注册了 ConfigurationClassPostProcessor 到容器里面
        // BeanDefinitionRegistryPostProcessor 实现了 BeanDefinitionRegistryPostProcessor
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 添加 bean
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 这里只添加了名字 后面用来判断谁已经执行过了
                processedBeans.add(ppName);
            }
        }
        // 排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 循环执行 processors 的 postProcessBeanDefinitionRegistry 方法
        // 这个得在仔细看
        // debug 看到 执行完这一步我另一个加 @Component 注解的类 注册到 Registry 里面了
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        // 清除
        currentRegistryProcessors.clear();
        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // 处理实现 Ordered 的 processor
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // 只有不包含的才执行, 执行完之后会添加进 processedBeans
            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();
        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // 最后执行其他
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 只有不包含的才执行, 执行完之后会添加进 processedBeans
                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();
        }
        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // 上面处理的都是 postProcessBeanDefinitionRegistry 是在 -> BeanDefinitionRegistryPostProcessor 中
        // 下面开始处理 postProcessBeanFactory  -> 是在 BeanFactoryPostProcessor 中
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // Invoke factory processors registered with the context instance.
        // 不是 BeanDefinitionRegistry 则是普通 BeanFactory 直接执行 beanFactoryPostProcessors 即可
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // 第二部分
    // 上面执行的是 BeanDefinitionRegistryPostProcessor
    // 下面开始执行 BeanFactoryPostProcessor
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 按照顺序执行
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
            // 说明上面已经执行了, 下面忽略
        } 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);
        }
    }
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // 执行实现 PriorityOrdered 的
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    // 清空不必要的元数据信息
    beanFactory.clearMetadataCache();
}

上面总体可以分为两部分:

  1. 执行 BeanDefinitionRegistryPostProcessor 接口里面的两个方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。
  2. 执行 BeanFactoryPostProcessor 接口里面的 postProcessBeanFactory 方法。


以第一部分为例:

  1. 首先判断传入的 BeanFactory 是否为 BeanDefinitionRegistry
  1. 声明两个 List 集合,regularPostProcessors 用来存储 BeanFactoryPostProcessor,registryProcessors 用来存储 BeanDefinitionRegistryPostProcessor
  1. 循环 beanFactoryPostProcessors,这个就是我们使用 API 方式添加进来的 BeanFactoryPostProcessor。
  2. 在循环中 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 会被执行,也就是说我示例的那个添加 BeanDefinition 演示的方法会被执行。
  1. 开始执行 Spring 自己的 BeanDefinitionRegistryPostProcessor, 处理顺序为 PriorityOrdered, Ordered, and the rest
  1. 循环,将对应的 BeanDefinitionRegistryPostProcessor 添加到 currentRegistryProcessors 集合和processedBeans集合表示为已经处理。
  2. 排序后添加到第一步的 registryProcessors 中。
  3. 调用 invokeBeanDefinitionRegistryPostProcessors 执行所有的 Processor 里面的 postProcessBeanDefinitionRegistry 方法
  1. 执行完 1 和 2 之后,所有的 postProcessBeanDefinitionRegistry 已经被执行完了,但是两个集合(registryProcessors、regularPostProcessors)里面的 postProcessBeanFactory 方法还没有被执行。最后会循环执行。
  1. 如果不是 BeanDefinitionRegistry 类型,则直接执行传入的 beanFactoryPostProcessors 即可。

下面是对应的代码截图

网络异常,图片无法展示
|

网络异常,图片无法展示
|

以上只是这个方法的前半部分,执行了 BeanDefinitionRegistryPostProcessor 里面的 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。

因为还有直接实现 BeanFactoryPostProcessor 的处理器,下面则开始处理 BeanFactoryPostProcessor 的处理器。过程和上面类似。


总结


通过以上的阅读,对 invokeBeanFactoryPostProcessors(beanFactory); 这一步方法进行总结。


BeanFactoryPostProcessor 作用

BeanFactoryPostProcessor 主要作用是在注册 BeanDefinition 之后,在 Bean 初始化之前,修改 BeanDefinition 的信息。

BeanFactoryPostProcessor 有个实现叫 BeanDefinitionRegistryPostProcessor,它可以额外的注册新的 BeanDefinition 到容器中。


流程概述

  1. 这一步主要是处理 BeanFactoryPostProcessor,分为两步。
  2. 执行 BeanDefinitionRegistryPostProcessor 接口里面的两个方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。
  3. 执行 BeanFactoryPostProcessor 接口里面的 postProcessBeanFactory 方法。

网络异常,图片无法展示
|



目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
1月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
22天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
41 2
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
67 9
|
2月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
43 9
|
1月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
33 0
|
2月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
28 1
|
2月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
168 5
|
2月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
2月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
105 2