BeanFactoryPostProcessor介绍及执行流程分析

一、基础知识

BFPP和BDRPP介绍

BeanFactoryPostProcessor的主要作用是对Bean的定义信息进行修改,即修改BeanDefinition。
一种比较常见的操作就是对BeanDefinition中的占位符替换成实际的值,如:

> <bean id="person" class="com.yk.entity.Person">
> 	<property name="id" value="${person.id}"/>
> 	<property name="name" value="${person.name}"/>
> </bean>

BeanDefinitionRegistryPostProcessor,是对BeanFactoryPostProcessor的一种扩展,BeanFactoryPostProcessor只侧重于对容器中的BeanDefinition进行修改,而BeanDefinitionRegistryPostProcessor除了具有BeanDefinitionPostProcessor的功能之外还可以对容器中的BeanDefinition进行增加和删除操作

类图:

在这里插入图片描述

BFPP代码:

public interface BeanFactoryPostProcessor {
    // 传入的是ConfigurableListableBeanFactory类型的对象
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

在这里插入图片描述

BDRPP代码:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	// 传入的是BeanDefinitionRegistry
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

在这里插入图片描述

二、自定义BFPP

自定义BFPP,只需要实现BeanFactoryPostProcessor接口并实现postProcessBeanFactory方法就行。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("Execute MyBeanFactoryPostProcessor.postProcessBeanFactory");
    }
}

定义了BFPP之后,Spring并不能自动识别到自定义的BFPP,需要我们做些额外的操作才行。
让Spring识别到自定义的BFPP的两种方式:

  • 方式一:

将自定义的BFPP作为一个Bean定义到配置文件中,即:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 	自定义的BFPP -->
  <bean class="com.yk.bfpp.MyBeanFactoryPostProcessor"></bean>
  <!--   自定义的BDRPP -->
	<bean class="com.yk.bfpp.MyBeanFactoryRegistryPostProcessor"></bean>
</beans>
  • 方式二:

在创建完IOC容器之后,有一个customizeBeanFactory的方法,我们通过重写这个方法,可以进行一些扩展实现。

protected final void refreshBeanFactory() throws BeansException {
		// ......
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// ......
            // 重新这个方法进行扩展实现
			customizeBeanFactory(beanFactory);
			// ......
		}
		// ......
	}

这个方法在AbstractRefreshableApplicationContext这个Java类中,直接继承这个文件是否可行?首先查看下我们常用的ApplicationContextClassPathXmlApplicationContext,查看一下两者的关系:
在这里插入图片描述

通过类图可以发现,ClassPathXmlApplicationContextAbstractRefreshableApplicationContext的一个子类,所以我们可以直接继承ClassPathXmlApplicationContext,并重新customizeBeanFactory方法,如果直接继承AbstractRefreshableApplicationContext我们的ApplicationContext会丢失掉AbstractXmlApplicationContextClassPathXmlApplicationContext中实现的功能。

两种实现方式有什么区别?

通过配置文件注册的BFPP和BDRPP会在解析XML配置文件的时候被解析成BeanDefinition,而通过customizeBeanFactory注册的BFPP和BDRPP不会被解析成BeanDefinition,我们在注册的时候就已经将其实例化。

BFPP的执行顺序

上面是实现BFPP的最简单形式,如果想改变下BFPP在系统中的执行顺序,可以让BFPP实现Ordered接口或者PriorityOrdered接口,其中实现PriorityOrdered接口的BFPP会优先与实现了Ordered接口的BFPP,实现了Ordered接口的BFPP会优先与未实现OrderedPriorityOrdered接口的BFPP;

三、自定义BDRPP

实现方式与BFPP大致相同。

四、BFPP在Spring中的执行流程分析

AbstractApplicationContext中的refresh()方法中会调用invokeBeanFactoryPostProcessors()方法,这个方法就是用来执行调用并执行BFPP的

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 执行BFPP的过程就是在这行代码中实现的
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // ......
}

上述代码首先会执行getBeanFactoryPostProcessors()方法,通过方法名猜测出它是来获取BFPP的?

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    // private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
    return this.beanFactoryPostProcessors;
}

可以看出,这个方法返回的是一个BFPP的列表,但这里并不是我们容器中所有的BFPP,而是我们通过重写customizeBeanFactory并在方法中添加类似于:this.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());这种代码注册进去的,而我们通过配置文件的并没有被注册到这个列表中,而是和其他Bean一样,被解析成了BeanDefinition,那这两种方式注册的BFPP分别是怎么被执行的?
执行流程:

  1. 首先是对通过customizeBeanFactory注册的BFPP和BDRPP进行处理
    1. 如果是BDRPP,那么就执行BDRPP的postProcessBeanDefinitionRegistry方法,并将其加入到一个集合中;
    2. 如果是BFPP,那么就将其加入到另外一个集合中;
  2. 继续获取BDRPP,此时获取的是通过XML配置文件注册的和系统中提供的BDRPP,它们都会被解析成BeanDefinition。
    1. 获取所有的实现了PriorityOrdered接口的BDRPP,对它们排序并依次执行postProcessBeanDefinitionRegistry方法;
    2. 获取所有的实现了Ordered接口的BDRPP,对它们排序并依次执行postProcessBeanDefinitionRegistry方法;
    3. 获取剩余的BDRPP并依次执行postProcessBeanDefinitionRegistry方法;
  3. 经过上面的两步操作,系统中所有的BDRPP都被记录在集合中,因为它们是BFPP的子类,所以它们也是BFPP,这里就是执行它们继承的BFPP的postProcessBeanFactory方法;
  4. 获取系统中的BFPP,并按照实现PriorityOrderedOrdered和未实现上面两个接口进行分组执行
    1. 执行实现了PriorityOrdered接口的BFPP,对它们排序并依次执行postProcessBeanFactory方法,若上面步骤中已经执行过则跳过执行操作;
    2. 执行实现了Ordered接口的BFPP,对它们排序并依次执行postProcessBeanFactory方法,若上面步骤中已经执行过则跳过执行操作;
    3. 执行剩余的BFPP的postProcessBeanFactory方法,若上面步骤中已经执行过则跳过执行操作;
  5. 到这里系统中所有的BDRPP和BFPP都已经处理完成。

下面是具体的代码及详细注释:

public static void invokeBeanFactoryPostProcessors(
    ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// 总的执行思路:
    // 因为BeanDefinitionRegistryPostProcessor可能会生成新的BeanDefinition,而BeanFactoryPostProcessor
    // 可能会对每一个BeanDefinition进行处理,所以BeanDefinitionRegistryPostProcessor必须要在
    // BeanFactoryPostProcessor执行之前进行执行。
    
    // 存放已经调用执行过的BeanFactoryPostProcessor的beanName
    Set<String> processedBeans = new HashSet<>();
	// 先处理通过重写customizeBeanFactory方法注册到容器中的BeanFactoryPostProcessor
    // beanFactory默认是DefaultListableBeanFactory,if条件成立
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 存放BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        // 存放BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // 如果当前postProcessor是BeanDefinitionRegistryPostProcessor,会先执行
            // 当前postProcessor的postProcessBeanDefinitionRegistry方法,然后把当前
            // postProcessor添加到registryProcessor集合中
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                    (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                // 如果当前postProcessor就是一个普通的BeanFactoryPostProcessor,那么把当前
                // postProcessor加入到regularPostProcessors
                regularPostProcessors.add(postProcessor);
            }
        }
        
        // 到这里为止,通过customizeBeanFactory方法注册到容器中的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry均已经执行完成。

        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 从这里开始,处理的是通过配置文件注册的自定义的BeanDefinitionRegistryPostProcessor和系统中提供的BeanDefinitionRegistryPostProcessor

        // 从容器中获取到类型为BeanDefinitionRegistryPostProcessor的beanName的一个数组
        String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

        // 获取到实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 这里会创建BeanDefinitionRegistryPostProcessor类型的对象
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // 获取到实现了Ordered接口的BeanDefinitionRegistryPostProcessor
        // 上面已经获取过一次了,这里重复获取的原因是在上面执行BDRPP的postProcessBeanDefinitionRegistry方法时可能会生成新的BDRPP
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                // 这里会创建BeanDefinitionRegistryPostProcessor类型的对象
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // 接下来是处理剩余的还未被处理的BDRPP
        boolean reiterate = true;
        // 这里循环执行原因依然是执行BDRPP的postProcessBeanDefinitionRegistry可能会生成新的BDRPP,所以循环执行,直至所有的BDRPP都被处理过。
        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);
            // 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

    	// 方法执行到这里,所有的BDRPP的postProcessBeanDefinitionRegistry都已被执行完成。
        
        // 接下来就是执行BFPP和BDRPP的postProcessBeanFactory方法

        // 这里执行用户自定义的BDRPP和Spring中定义的BDRPP的postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 这里执行用户自定义的BFPP的postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }
    else {
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 方法执行到这里,所有自定义的BFPP和系统中所有的BDRPP均已调用完成,接下来就是处理系统中的BFPP

    // 获取系统中的BFPP,这里获取的BFPP包括通过配置文件注册到Spring中的自定义的BFPP和系统中自带的BFPP
    // 获取BeanFactoryPostProcessor类型的beanName
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    // 遍历获取到的BFPP
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // BFPP已经被处理过则不做任何操作
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 实现了PriorityOrdered接口的BFPP,这里通过getBean会创建BFPP类型的对象,所以下面在执行BFPP的时候不需要再进行对象创建
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 实现了Ordered接口的BFPP,这里存入的只是beanName
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 剩余的BFPP,这里存入的只是beanName
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 对实现了PriorityOrdered接口的BFPP进行排序,然后执行BFPP的postProcessBeanFactory方法
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 对实现了Ordered接口的BFPP进行实例化,然后排序和执行postProcessBeanFactory方法
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 对未实现了PriorityOrdered和Ordered接口的BFPP(也就是剩余的BFPP)进行实例化,然后执行postProcessBeanFactory方法
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
    beanFactory.clearMetadataCache();
}

参考链接:
https://blog.csdn.net/aqin1012/article/details/125189197
参考书籍:
《Spring源码深度解析第二版》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值