目录

一、定义

二、自定义BeanFactoryPostProcessor实现类

三、BeanFactoryPostProcessor执行细节

四、BeanFactoryPostProcessor常用子类


一、定义

官网对BeanFactoryPostProcessor的描述如下:

  • Spring IoC容器允许我们自定义BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义信息(配置元数据),并修改它,如我们可以把某个bean的scope从singleton改为prototype,也可以把bean的属性值给修改掉,还可以往bean工厂中新增加bean定义等等
  • BeanFactoryPostProcessor可以操作BeanDefinition,但是千万不要进行bean实例化操作,这样做可能会导致过早的bean实例化,违反了容器导致意想不到的副作用。如果bean实例交互是必需的,考虑使用BeanPostProcessor后置处理器;

BeanFactoryPostProcessor是一个函数式接口,其定义如下:

@FunctionalInterface
public interface BeanFactoryPostProcessor {// 此方法在Bean对象实例化之前执行,可以通过beanFactory可以获取bean的定义信息,然后修改bean的定义信息void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

BeanFactoryPostProcessor是在Spring容器加载了bean的定义信息之后,在bean实例化之前执行的。

二、自定义BeanFactoryPostProcessor实现类

如果需要自定义BeanFactoryPostProcessor的话,我们只需要实现BeanFactoryPostProcessor接口,并重写postProcessorBeanFactory()方法。下面我们通过一个简单的示例说明自定义BeanFactoryPostProcessor的用法,通过beanFactory获取bean的定义信息,并修改bean的定义信息。

  • (一)、编写一个简单的bean
public class Student implements Serializable {private String id;private String name;private Integer age;public Student() {System.out.println("Student实例化...");}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"id='" + id + '\'' +", name='" + name + '\'' +", age=" + age +'}';}
}
  • (二)、编写BeanFactoryPostProcessor实现类
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;/*** @Description: 自定义BeanFactoryPostProcessor* @Date: 2021/12/23 11:16* 说明: BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它* 可以通过实现Ordered接口指定order属性的值,从而设置BeanFactoryPostProcessor的执行顺序,order属性的值越小,优先级越高*/
public class MyBeanFactoryPostProcessor01 implements BeanFactoryPostProcessor, Ordered {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("执行MyBeanFactoryPostProcessor01的postProcessBeanFactory()方法");// 获取工厂当前所有注册的beanNames数组String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();// 循环遍历for (String beanName : beanDefinitionNames) {if ("student".equals(beanName)) {// 根据beanName获取对应的bean定义信息// 当我们拿到BeanDefinition对象后,我们可以手动修改bean标签中所定义的属性值BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);// 获取对应的属性值MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();// 更新属性值if (propertyValues.contains("name")) {System.out.println("修改name属性...旧值:" + propertyValues.get("name"));propertyValues.add("name", "李四");}}}}@Overridepublic int getOrder() {return 0;}
}public class MyBeanFactoryPostProcessor02 implements BeanFactoryPostProcessor, Ordered {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("执行MyBeanFactoryPostProcessor02的postProcessBeanFactory()方法");// 获取工厂当前所有注册的beanNames数组String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();// 循环遍历for (String beanName : beanDefinitionNames) {if ("student".equals(beanName)) {// 根据beanName获取对应的bean定义信息// 当我们拿到BeanDefinition对象后,我们可以手动修改bean标签中所定义的属性值BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);// 获取对应的属性值MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();// 更新属性值if (propertyValues.contains("age")) {System.out.println("修改age属性...旧值:" + propertyValues.get("age"));propertyValues.add("age", "20");}}}}@Overridepublic int getOrder() {return 1;}
}

可以实现Ordered接口,指定order属性的值,从而改变各个BeanFactoryPostProcessor执行顺序,order的值越小,BeanFactoryPostProcessor执行的优先级越高。

  • (三)、编写spring配置文件,注册自定义的BeanFactoryPostProcessor、bean信息
<!--自定义BeanFactoryPostProcessor-->
<bean id="student" class="com.wsh.beanfactorypostprocessor.Student"><property name="id" value="1"/><property name="name" value="张三"/><property name="age" value="10"/>
</bean>
<bean id="myBeanFactoryPostProcessor01" class="com.wsh.beanfactorypostprocessor.MyBeanFactoryPostProcessor01"/>
<bean id="myBeanFactoryPostProcessor02" class="com.wsh.beanfactorypostprocessor.MyBeanFactoryPostProcessor02"/>
  • (四)、测试类
public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");System.out.println(applicationContext.getBean("student"));}
}
  • (五)、运行结果
执行MyBeanFactoryPostProcessor01的postProcessBeanFactory()方法
修改name属性...旧值:TypedStringValue: value [张三], target type [null]
执行MyBeanFactoryPostProcessor02的postProcessBeanFactory()方法
修改age属性...旧值:TypedStringValue: value [10], target type [null]
Student实例化...
Student{id='1', name='李四', age=20}

从输出结果,我们可以看出postProcessBeanFactory()方法执行的顺序是在Bean实例化之前,并且通过自定义BeanFactoryPostProcessor把bean的属性给覆盖了。

三、BeanFactoryPostProcessor执行细节

  • BeanFactoryPostProcessor的执行时机?

熟悉Spring IOC容器刷新流程的话,应该很容易想到,BeanFactoryPostProcessor的执行时机就是在容器刷新核心方法refresh()方法中的第五步:invokeBeanFactoryPostProcessors(beanFactory)方法。

从AbstractApplicationContext#refresh()方法开始,找到invokeBeanFactoryPostProcessors(beanFactory)方法:

可以看到,执行invokeBeanFactoryPostProcessors(beanFactory)方法之前,配置文件中的bean定义信息已经被封装到beanDefinitionMap中了。

invokeBeanFactoryPostProcessors()方法实现如下:

// 实例化并调用所有已注册的BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 1.拿到当前应用上下文beanFactoryPostProcessors变量中的值// 2.实例化并调用所有已注册的BeanFactoryPostProcessorPostProcessorRegistrationDelegate.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 (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

简述一下invokeBeanFactoryPostProcessors()的处理流程:

  • (1)、首先对BeanFactoryPostProcessor的子类BeanDefinitionRegistryPostProcessor进行处理,从容器找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean,然后按照优先级进行排序后,依次回调BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法;
  • (2)、接着处理普通的BeanFactoryPostProcessor接口,同样的,从容器找出所有实现BeanFactoryPostProcessor接口的Bean,使用三个不同的集合,分别存放实现了PriorityOrdered接口、实现了Ordered接口、普通的BeanFactoryPostProcessor。接着按照优先级排序后,会执行postProcessBeanFactory()回调;

下面是具体的代码实现:

// org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.// 记录已经处理过的BeanFactoryPostProcessor集合,无需重复执行Set<String> processedBeans = new HashSet<>();// 对BeanDefinitionRegistry类型的处理if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// 存放普通的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();// 存放BeanDefinitionRegistryPostProcessor,BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessorList<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();// 循环遍历硬编码方式注册的BeanFactoryPostProcessor后置处理器for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {// 区分普通的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,分别放入不同的集合中if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;// 如果是BeanDefinitionRegistryPostProcessor的话,直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法registryProcessor.postProcessBeanDefinitionRegistry(registry);// BeanDefinitionRegistryPostProcessorregistryProcessors.add(registryProcessor);}else {// 普通BeanFactoryPostProcessorregularPostProcessors.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.// 记录本次要执行的BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();// 配置注册的后置处理器// 1、调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类// 找出所有实现BeanDefinitionRegistryPostProcessor接口的BeanString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 循环遍历,判断是否实现PriorityOrdered接口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);// 调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();// 2、调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类// 找出所有实现BeanDefinitionRegistryPostProcessor接口的类postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 循环遍历,判断是否实现Ordered接口for (String ppName : postProcessorNames) {// 未执行过 && 实现Ordered接口if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 添加到将要执行的集合中,避免重复执行processedBeans.add(ppName);}}// 按照order排序sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);// 调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();// 3、调用所有剩下的BeanDefinitionRegistryPostProcessorsboolean 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);// 调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();}// 回调所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);// 回调普通BeanFactoryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// 调用在上下文实例中注册的工厂处理器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!// 从bean工厂中获取到BeanFactoryPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.// 存放实现了PriorityOrdered接口的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 存放实现了Ordered接口的BeanFactoryPostProcessorList<String> orderedPostProcessorNames = new ArrayList<>();// 存放其它BeanFactoryPostProcessorList<String> nonOrderedPostProcessorNames = new ArrayList<>();// 循环从工厂中获取的BeanFactoryPostProcessor, 分别存入到三个不同的集合中for (String ppName : postProcessorNames) {// 针对已经处理过的BeanFactoryPostProcessor,不做任何操作,无需重复执行if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// PriorityOrdered接口的BeanFactoryPostProcessorpriorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// Ordered接口的BeanFactoryPostProcessororderedPostProcessorNames.add(ppName);}else {// 普通BeanFactoryPostProcessornonOrderedPostProcessorNames.add(ppName);}}// 1、调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor// 排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 执行postProcessBeanFactory()回调invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 2、调用所有实现Ordered接口的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();for (String postProcessorName : orderedPostProcessorNames) {// 这里会触发BeanFactoryPostProcessor的创建流程orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}// 排序sortPostProcessors(orderedPostProcessors, beanFactory);// 执行postProcessBeanFactory()回调invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 3、调用所有其他BeanFactoryPostProcessorList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}// 执行postProcessBeanFactory()回调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();
}

通过beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false),获取Spring配置文件中定义的所有实现BeanFactoryPostProcessor接口的bean,然后根据优先级进行排序,如下图:

针对每个BeanFactoryPostProcessor,调用postProcessBeanFactory方法:

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {// 回调postProcessBeanFactory()方法postProcessor.postProcessBeanFactory(beanFactory);}
}

如下图:

以上就是BeanFactoryPostProcessor具体的执行流程。

四、BeanFactoryPostProcessor常用子类

BeanFactoryPostProcessor有几个比较常用的子类,下面简单列举一些:

  • BeanDefinitionRegistryPostProcessor:可以注册更多的BeanDefinition,在BeanFactoryPostProcessor调用之前。该接口也只有一个方法postProcessBeanDefinitionRegistry()。
  • PropertySourcesPlaceholderConfigurer:解析XML配置文件中的${xxx}占位符,将${xxx}替换为指定的properties文件中的值 ;
  • ConfigurationClassPostProcessor:解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解;
  • .......

BeanFactoryPostProcessor是Spring提供给我们的一个扩展点,通过BeanFactoryPostProcessor,我们可以在bean实例化之前做一些逻辑处理,比如修改一些bean定义里面的属性值等,我们从其作用、自定义实现示例、以及具体的执行流程等方面介绍了BeanFactoryPostProcessor,在实际项目中,我们可以根据具体的场景自定义BeanFactoryPostProcessor。

希望本篇文章对大家有所帮助,也希望大家能指出不对之处。这应该是2021年总结的最后一篇文章啦,最后祝大家2022年新年快乐吧,2022年希望自己能继续坚持学习,每天进步一点点!

Spring扩展之BeanFactoryPostProcessor接口相关推荐

  1. Spring BeanFactoryPostProcessor接口详细使用

    BeanFactoryPostProcessor接口简介 Spring容器在初始化之前,允许我们自定义扩展改变bean的定义,BeanFactoryPostProcessor正好可以满足我们的要求,B ...

  2. spring成神之路第二十九篇:BeanFactory 扩展(BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor)...

    Spring中有2个非常重要的接口:BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,这2个接口面试中也会经常问到,本文我们一起 ...

  3. Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析

    首先下面是我的Bean /** Copyright 2002-2017 the original author or authors.** Licensed under the Apache Lice ...

  4. BeanFactoryPostProcessor接口(容器后处理器)

    2019独角兽企业重金招聘Python工程师标准>>> 容器后处理器后处理容器本身.必须实现BeanFactoryPostProcessor接口,该接口中有如下方法: postPro ...

  5. Spring扩展点总结

    经历了一系列复杂的spring应用后,你的项目可能已经用上注解,也用上了xxx.properties,你对这神奇的用法感到欣喜,但你不知道他是怎么被实现的,现在就让我们来揭开这些神秘的面纱. Bean ...

  6. spring注解驱动开发-8 Spring 扩展原理

    Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...

  7. spring中基础核心接口总结

    spring中基础核心接口总结 理解这几个接口,及其实现类就可以快速了解spring,具体的用法参考其他spring资料 1.BeanFactory最基础最核心的接口 重要的实现类有: XmlBean ...

  8. 框架:Spring之Aware相关接口

    一.Aware相关接口 对于应用程序来说,应该尽量减少对Sping Api的耦合程度,然而有些时候为了运用Spring所提供的一些功能,有必要让Bean了解Spring容器对其进行管理的细节信息,如让 ...

  9. spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入...

    <spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...

  10. spring中的aware接口

    1.实现了相应的aware接口,这个类就获取了相应的资源. 2.spring中有很多aware接口,包括applicationContextAware接口,和BeanNameAware接口. 实现了这 ...

最新文章

  1. c语言职专试题及答案,中等职业学校计算机应用专业c语言编程基础科试卷及答案.doc...
  2. 试用了一下sourceMonitor有点不知所云..
  3. java中fitlter,068.Python框架Django之DRF视图集使用
  4. node定时任务php 卡,在NodeJs中如何实现定时任务(详细教程)
  5. E20170603-ts
  6. 计算机二级c语言考点变化,计算机二级C语言考点归纳汇总.doc
  7. 20岁生日 nyoj 312(闰年算法)
  8. 差分脉冲编码调制(DPCM)编码过程详解
  9. 同或门真值表_三输入异或门真值表计算详解
  10. Unity 用于控制摄像机的旋转、远近
  11. 谈莉娜,也被淘汰,社会真是太黑暗了,哎!
  12. 简单易懂的CRC校验原理阐述
  13. GAMMA初学笔记三
  14. matlab查看hdf5数据,Matlab 操作 HDF5文件
  15. 《那些年啊,那些事——一个程序员的奋斗史》——43
  16. [bzoj4735] 你的生命已如风中残烛
  17. 大数据实战项目之电商数仓(一)
  18. ECharts自定义toolbox中增加自定义按钮
  19. 抚顺学计算机到哪个学校好,抚顺有什么大学
  20. 使用树莓派搭建私人存储云盘

热门文章

  1. hadoop 如何连beeline_Hadoop家族新成员Hbase重磅来袭
  2. 2021-09-08FTRL 跟随正确的领导者
  3. 395.至少有K个重复字符的最长子串
  4. 整数与IP地址间的转换
  5. 深度学习框架PyTorch:入门与实践 学习(一)
  6. [译]直观理解信息论
  7. 【POJ-2796】Feel Good【单调栈】
  8. HDU5961 —— 传递【竞赛图】【判断传递闭包】
  9. Matrix Cookbook 公式推导
  10. ubuntu facebook/C3D视频特征提取