关于BeanPostProcessor和BeanFactoryPostProcessors,将分2篇文章来写,这篇文章是对Spring 中BeanPostProcessor进行了总结
先看下大模型对这个类的介绍,随后再看下这两个类的示例,最后看下这两个类的实现。
这两个类从名字看都很类似,见名知意:BeanPostProcessor=Bean后置处理器,BeanFactoryPostProcessors=BeanFactory后置处理器
BeanPostProcessor
在Spring 5.3中,BeanPostProcessor是一个强大的接口,它允许开发者在Spring容器中的bean实例化、配置和初始化前后添加自定义的逻辑处理。以下是关于BeanPostProcessor的详细解释:
1. 作用阶段
BeanPostProcessor在Spring容器完成bean的实例化、配置和其他的初始化前后工作。它提供了两个方法,一个在初始化方法之前执行,另一个在初始化方法之后执行。
2. 主要方法
postProcessBeforeInitialization(Object bean, String beanName):
在bean的初始化方法(如@PostConstruct标记的方法或实现InitializingBean接口中的afterPropertiesSet方法)被调用之前执行。
允许在bean的属性被设置之后,但在初始化之前,对bean进行额外的处理。
postProcessAfterInitialization(Object bean, String beanName):
在bean的初始化方法被调用之后执行。
允许在bean完成初始化后,对其进行修改或返回一个新的对象(尽管这通常不是推荐的做法,因为可能导致意外的行为)。
3. 返回值
这两个方法都不能返回null。如果返回null,那么在后续的操作中可能会遇到空指针异常,或者通过getBean()方法无法获取到bean的实例。
4. 使用方式
要使用BeanPostProcessor,你需要:
实现BeanPostProcessor接口。
实现postProcessBeforeInitialization和postProcessAfterInitialization方法。
将你的BeanPostProcessor实现注册为Spring容器中的一个bean,这样Spring就能够识别并应用它。
5. 排序和优先级
如果在Spring配置中定义了多个BeanPostProcessor,那么默认情况下,Spring容器会根据它们的定义顺序来依次调用。
但是,你可以通过实现Ordered接口或使用@Order、@Priority注解来指定优先级。
6. 应用场景
BeanPostProcessor常被用于AOP(面向切面编程)的自动代理创建、日志记录、安全检查、性能监控等场景。
7. 注意事项
由于BeanPostProcessor能够影响所有bean的初始化过程,因此在使用时需要特别小心,避免引入不必要的复杂性或错误。
如果在postProcessBeforeInitialization或postProcessAfterInitialization方法中修改了bean的状态,需要确保这些修改是预期的,并且不会对其他bean或整个应用程序产生负面影响。
8. 总结
BeanPostProcessor是Spring框架中一个非常强大的工具,它允许开发者在bean的生命周期中的关键阶段插入自定义逻辑。然而,由于其强大的能力,使用时需要谨慎,并确保理解其工作原理和潜在影响。
现在写几个示例来看下是怎么执行的。
我这里定义A、B、C、D 、E、F类,分别如下:
A类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* 注解方式
*/
@Component
public class A implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("A.postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("A.postProcessAfterInitialization");
return bean;
}
}
B类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 注解方式,加了顺序
*/
@Component
@Order(0)
public class B implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("B.postProcessBeforeInitialization, order: 0");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("B.postProcessAfterInitialization, order: 0");
return bean;
}
}
C类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
/**
* 注解方式,实现Order
*/
@Component
public class C implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("C.postProcessBeforeInitialization, order: 1");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("C.postProcessAfterInitialization, order: 1");
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
D类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;
/**
* 注解方式,实现PriorityOrdered
*/
@Component
public class D implements BeanPostProcessor, PriorityOrdered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("D.postProcessBeforeInitialization, PriorityOrdered: 2");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("D.postProcessAfterInitialization, PriorityOrdered: 2");
return bean;
}
@Override
public int getOrder() {
return 2;
}
}
E类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;
/**
* 注解方式,实现PriorityOrdered
*/
@Component
public class E implements BeanPostProcessor, PriorityOrdered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("E.postProcessBeforeInitialization, PriorityOrdered: 3");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("E.postProcessAfterInitialization, PriorityOrdered: 3");
return bean;
}
@Override
public int getOrder() {
return 3;
}
}
F类
package org.springframework.example.BPP;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
/**
* 注解方式,实现Order
*/
@Component
public class F implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("F.postProcessBeforeInitialization, order: 4");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("F.postProcessAfterInitialization, order: 4");
return bean;
}
@Override
public int getOrder() {
return 4;
}
}
BeanTest 测试类
package org.springframework.example.BPP;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext("org.springframework.example.BPP");
}
}
看下打印结果
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
C.postProcessBeforeInitialization, order: 1
F.postProcessBeforeInitialization, order: 4
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
C.postProcessAfterInitialization, order: 1
F.postProcessAfterInitialization, order: 4
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
C.postProcessBeforeInitialization, order: 1
F.postProcessBeforeInitialization, order: 4
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
C.postProcessAfterInitialization, order: 1
F.postProcessAfterInitialization, order: 4
初步分析结果,后面再看原因:
1、打印的结果怎么是这样
2、AB为什么没有打印
3、PriorityOrdered 优先级高于Ordered
4、B类的@Order(0)好像没用
带着问题,来分析一下源码:
首先我们的BeanTest类里面的AnnotationConfigApplicationContext,new 的时候内部自带了refresh(),在refresh()里面找到registerBeanPostProcessors(beanFactory),最后在PostProcessorRegistrationDelegate类的registerBeanPostProcessors中打个断点,后面调试用。
先整体分析一下这段代码:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
//上面的注释看,作者意思是这样写很多循环都是有意的,不需要重构
//获取BeanPostProcessor的实现类的Bean名称集合
//抛开Spring自带的BeanPostProcessor,这里将会获取到我们自定义的ABCDEF6个类,Spring 自带的BeanPostProcessor,后面再说
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
//这里为什么要+1,我个人估计是因为BeanPostProcessorChecker本身也是一个BeanPostProcessor
//BeanPostProcessorChecker 用来检测不符合BeanPostProcessors规则的Bean
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//分别收集PriorityOrdered、Ordered和没有实现排序的BeanPostProcessor和MergedBeanDefinitionPostProcessor类型的Bean
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
//查询指定名称的Bean 是否实现PriorityOrdered 接口,判断的代码也挺复杂,暂且不关心
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//获取BeanPostProcessor的实例
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
//如果是MergedBeanDefinitionPostProcessor类型,该处理器后面再说
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//如果实现了Ordered接口,则添加到orderedPostProcessorNames集合中
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
//如果没有实现排序接口,则添加到nonOrderedPostProcessorNames集合中
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
//先排序priorityOrderedPostProcessors
//默认排序规则使用的OrderComparator,优先排序PriorityOrdered的实现类,顺序从小到大排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//注册,就是往beanFactory中的一个List增加BeanPostProcessor
//这里面又判断了beanFactory 是否是AbstractBeanFactory,关于什么事AbstractBeanFactory,也留着后面讲
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
//注册实现了Ordered的BeanPostProcessors
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
//同样判断了MergedBeanDefinitionPostProcessor
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//同理,排序
sortPostProcessors(orderedPostProcessors, beanFactory);
//同理,注册
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
//处理没有实现排序的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//同理,注册
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
//最后,处理MergedBeanDefinitionPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
//添加ApplicationListenerDetector,其用来注册ApplicationListener类型的bean到上下文中,后面来测试一下
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
下面来调试一下
解释第一个问题,打印结果解密,首先要知道在哪里调用postProcessBeforeInitialization和postProcessAfterInitialization。这里是在通过beanFactory.getBean获取Bean的时候,没有Bean就会创建一个Bean,此时就会调用到,跟进去在AbstractAutowireCapableBeanFactory–>initializeBean 内部进行调用,此处打个断点调式。
由于几个内置BeanPostProcessor的存在,运行时会多次进入断点,所以我们都跳过,进入applyBeanPostProcessorsBeforeInitialization,查看**getBeanPostProcessors()**的值,此时为几个内置BeanPostProcessor。
内置Bean自然没有我们的东西,跳过,后面的进入断点次数,不算内置BeanPostProcessor!!!。
第二次进入断点,此时beanName 是 e
此时的getBeanPostProcessors() 还是原来的内置BeanPostProcessor,跳过。
第三次进入断点,此时beanName是“c”
这时getBeanPostProcessors() 多了D、E,这时继续执行,将打印D、E的postProcessBeforeInitialization日志
继续往下执行到applyBeanPostProcessorsAfterInitialization,打印
到这里,Bean C已经处理完了,直接跳过,到下个断点
第四次进入断点是F
这里的getBeanPostProcessors() 还是DE,没有C,为什么?因为CF都是实现的Ordered,他们都是在一块处理,处理完后才添加到beanPostProcessors中。由前面的代码分析可知。
所以在这里还是打印的DE的日志。
第五次进入断点,beanName是a
这里开始打印DECF的日志
第六次进入断点,beanName是b
到这里所有的类都执行完了
解释一下第二个问题,AB为什么没有被打印。
从上面可知,AB 两个bean的创建在最后,后续没有其他Bean创建,因此没有执行AB 两个BeanPostProcessor的机会。要想打印,单独创建一个普通Bean,来测试一下。
G类
package org.springframework.example.BPP;
import org.springframework.stereotype.Component;
@Component
public class G {
}
这里发现一个问题,B类的order 是0,怎么会在最后?实际是因为B类被认为是没有实现排序的BeanPostProcessor,也就是 Order(0) 注解在这里没用!!!这也就回答了第四个问题。
解释第三个问题,PriorityOrdered 优先级高于Ordered,因为代码是先处理的PriorityOrdered 的实现
最后对于大模型对BeanPostProcessor的介绍中的第五点
5. 排序和优先级
如果在Spring配置中定义了多个BeanPostProcessor,那么默认情况下,Spring容器会根据它们的定义顺序来依次调用。
但是,你可以通过实现Ordered接口或使用@Order、@Priority注解来指定优先级。
是错误的!!!目前只能通过实现Ordered或者PriorityOrdered接口
通过上面的实例测试@Order并没有起作用,@Priority 注解也没法在类上使用,查了一下该注解在javax.annotation-api中。
作者其他文章推荐:
基于Spring Boot 3.1.0 系列文章
- Spring Boot 源码阅读初始化环境搭建
- Spring Boot 框架整体启动流程详解
- Spring Boot 系统初始化器详解
- Spring Boot 监听器详解
- Spring Boot banner详解
- Spring Boot 属性配置解析
- Spring Boot 属性加载原理解析
- Spring Boot 异常报告器解析
- Spring Boot 3.x 自动配置详解