前言
BeanDefinitionRegistryPostProcessor , BeanFactoryPostProcessor ,InstantiationAwareBeanPostProcessor, BeanPostProcessor是spring生命周期中常见的4个后置处理器,但是对于其作用和执行顺序很多人还不是非常清楚,这里给大家讲解一下其作用以及执行顺序,并带上实操。
生命周期图:
作用及其执行顺序
-
BeanDefinitionRegistryPostProcessor 是一个扩展了 BeanFactoryPostProcessor 的接口,它可以在 Spring 容器加载了所有的 bean 定义之后,但是在 bean 实例化之前,对 bean 的定义进行修改或者添加 。它的 postProcessBeanDefinitionRegistry 方法会在所有的 bean 定义被加载后,但是在任何 bean 实例化之前被调用。它的 postProcessBeanFactory 方法会在所有的 bean 实例化之后被调用。因此,它的执行顺序是最先执行 postProcessBeanDefinitionRegistry 方法,然后执行 postProcessBeanFactory 方法。
-
BeanFactoryPostProcessor 是一个可以在 Spring 容器加载了所有的 bean 定义之后,但是在 bean 实例化之前,对 bean 的定义进行修改或者添加的接口 。它的 postProcessBeanFactory 方法会在所有的 bean 定义被加载后,但是在任何 bean 实例化之前被调用。因此,它的执行顺序是在 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法之后,但是在 BeanDefinitionRegistryPostProcessor 的 postProcessBeanFactory 方法之前。
-
InstantiationAwareBeanPostProcessor 是一个扩展了 BeanPostProcessor 的接口,它可以在 Spring 容器实例化 bean 的过程中,对 bean 进行修改或者增强。它有四个方法:postProcessBeforeInstantiation、postProcessAfterInstantiation、postProcessPropertyValues 和 postProcessBeforeInitialization。它的执行顺序是:
- 在每个 bean 实例化之前,调用 postProcessBeforeInstantiation 方法,如果该方法返回非空对象,则跳过后续的实例化过程。
- 在每个 bean 实例化之后,调用 postProcessAfterInstantiation 方法,如果该方法返回 false,则跳过后续的属性注入过程。
- 在每个 bean 属性注入之前,调用 postProcessPropertyValues 方法,如果该方法返回非空属性值,则使用返回的属性值进行注入。
- 在每个 bean 初始化之前,调用 postProcessBeforeInitialization 方法,如果该方法返回非空对象,则使用返回的对象作为初始化结果。
-
BeanPostProcessor 是一个可以在 Spring 容器实例化和初始化 bean 的过程中,对 bean 进行修改或者增强的接口 。它有两个方法:postProcessBeforeInitialization 和 postProcessAfterInitialization。它的执行顺序是:
-
在每个 bean 初始化之前,调用 postProcessBeforeInitialization 方法,如果该方法返回非空对象,则使用返回的对象作为初始化结果。
-
在每个 bean 初始化之后,调用 postProcessAfterInitialization 方法,如果该方法返回非空对象,则使用返回的对象作为最终结果。
-
总结一下,这几个接口的执行顺序和作用如下:
- BeanDefinitionRegistryPostProcessor: 最先执行,在所有的 bean 定义被加载后,可以修改或者添加 bean 的定义。
- BeanFactoryPostProcessor: 其次执行,在所有的 bean 定义被加载后,可以修改或者添加 bean 的定义。
- InstantiationAwareBeanPostProcessor: 第三执行,在每个 bean 实例化和初始化的过程中,可以修改或者增强 bean 的对象和属性。
- BeanPostProcessor: 最后执行,在每个 bean 初始化的过程中,可以修改或者增强 bean 的对象。
PostProcessor 类型 | 处理目标 | 执行时机 | 可操作的空间 |
---|---|---|---|
BeanDefinitionRegistryPostProcessor | BeanDefinition、.class 文件等 | 配置文件、配置类已解析完毕并注册进 BeanFactory,但还没有被 BeanFactoryPostProcessor 处理 | 向 BeanFactory 中注册新的 BeanDefinition |
BeanFactoryPostProcessor | BeanDefinition | BeanDefinition 解析完毕并注册进 BeanFactory 之后(此时 bean 未实例化) | 给 BeanDefinition 中增删属性、移除 BeanDefinition 等 |
InstantiationAwareBeanPostProcessor | bean 实例 | bean 的实例化阶段前后(在实例化 bean 对象之前和之后) | 在 bean 实例化的过程中,可以对实例化的 bean 进行定制化的操作,例如自定义实例化逻辑、修改实例化后的属性值等 |
BeanPostProcessor | bean 实例 | bean 的初始化阶段前后(已创建出 bean 对象) | 给 bean 的属性赋值、创建代理对象等 |
举例说明实际应用场景
- BeanDefinitionRegistryPostProcessor: 这个后置处理器可以在 bean 定义加载后,创建并注册新的 bean 定义,或者修改或者删除已有的 bean 定义。它可以用于动态地根据条件或者配置来增加或者减少 bean 的数量和类型。例如,我们可以根据不同的环境(开发、测试、生产)来注册不同的数据源或者缓存 bean,或者根据不同的功能模块来注册不同的服务 bean。一个具体的例子是 Spring Boot 的自动配置功能,它使用了一个名为 AutoConfigurationImportSelector 的 BeanDefinitionRegistryPostProcessor 来根据条件注解和配置文件来自动导入和注册合适的自动配置类。
- BeanFactoryPostProcessor: 这个后置处理器可以在 bean 定义加载后,修改或者添加已有的 bean 定义,但是不能创建或者删除 bean 定义。它可以用于修改 bean 的属性值、作用域、初始化方法等元数据信息。例如,我们可以根据外部的配置文件或者环境变量来修改 bean 的属性值,或者根据需要来改变 bean 的单例或者原型模式。一个具体的例子是 Spring 的 PropertyPlaceholderConfigurer 类,它使用了一个 BeanFactoryPostProcessor 来解析和替换 bean 定义中的占位符为实际的属性值。
- InstantiationAwareBeanPostProcessor: 这个后置处理器可以在每个 bean 实例化和初始化的过程中,修改或者增强 bean 的对象和属性。它可以用于控制 bean 的实例化过程,或者对 bean 的属性进行自定义的注入或者验证。例如,我们可以使用它来实现一些特殊的注解功能,如 @Autowired 或者 @Value,或者使用它来实现一些代理功能,如 AOP 或者事务管理。一个具体的例子是 Spring 的 AutowiredAnnotationBeanPostProcessor 类,它使用了一个 InstantiationAwareBeanPostProcessor 来实现了 @Autowired 和 @Value 注解的功能。
- BeanPostProcessor: 这个后置处理器可以在每个 bean 初始化的过程中,修改或者增强 bean 的对象。它可以用于对 bean 进行一些额外的配置或者初始化操作,或者对 bean 进行一些装饰或者代理操作。例如,我们可以使用它来执行一些初始化方法,如 @PostConstruct 或者 init-method,或者使用它来实现一些代理功能,如 AOP 或者事务管理。一个具体的例子是 Spring 的 InitDestroyAnnotationBeanPostProcessor 类,它使用了一个 BeanPostProcessor 来实现了 @PostConstruct 和 @PreDestroy 注解的功能。
实操
首先,我们需要创建一个 Spring Boot 项目,并在 pom.xml 中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
然后,我们需要定义以下四个后置处理器的实现类,并使用 @Component 注解标注它们,以便让 Spring 自动扫描并注册它们:
- MyBeanDefinitionRegistryPostProcessor:用于在 bean 定义加载后,创建并注册新的 bean 定义
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry");
// 创建一个新的 bean 定义
BeanDefinition beanDefinition = new RootBeanDefinition(MyNewBean.class);
// 注册到容器中
registry.registerBeanDefinition("myNewBean", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory");
// 修改已有的 bean 定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("helloService");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
- MyBeanFactoryPostProcessor:用于在 bean 定义加载后,修改或者添加已有的 bean 定义
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory");
// 修改已有的 bean 定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("worldService");
beanDefinition.setLazyInit(true);
}
}
- MyInstantiationAwareBeanPostProcessor:用于在每个 bean 实例化和初始化的过程中,修改或者增强 bean 的对象和属性
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation: " + beanName);
// 如果返回非空对象,则跳过后续的实例化过程
if (beanName.equals("myNewBean")) {
return new MyNewBean("Created by postProcessBeforeInstantiation");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation: " + beanName);
// 如果返回 false,则跳过后续的属性注入过程
if (beanName.equals("helloService")) {
return false;
}
return true;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues: " + beanName);
// 如果返回非空属性值,则使用返回的属性值进行注入
if (beanName.equals("worldService")) {
return new MutablePropertyValues().add("message", "Modified by postProcessPropertyValues");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization: " + beanName);
// 如果返回非空对象,则使用返回的对象作为初始化结果
if (beanName.equals("myNewBean")) {
return new MyNewBean("Modified by postProcessBeforeInitialization");
}
return bean;
}
}
- MyBeanPostProcessor:用于在每个 bean 初始化的过程中,修改或者增强 bean 的对象
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization: " + beanName);
// 如果返回非空对象,则使用返回的对象作为初始化结果
if (beanName.equals("helloService")) {
return new HelloService("Modified by postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization: " + beanName);
// 如果返回非空对象,则使用返回的对象作为最终结果
if (beanName.equals("worldService")) {
return new WorldService("Modified by postProcessAfterInitialization");
}
return bean;
}
}
接下来,我们需要定义以下四个普通的 bean 类,并使用 @Component 或者 @Service 注解标注它们,以便让 Spring 自动扫描并注册它们:
- HelloService:用于测试 MyBeanFactoryPostProcessor 和 MyInstantiationAwareBeanPostProcessor 的修改效果
@Service
public class HelloService {
private String message;
public HelloService() {
this.message = "Hello, Spring!";
}
public HelloService(String message) {
this.message = message;
}
public void sayHello() {
System.out.println(message);
}
}
- WorldService:用于测试 MyBeanFactoryPostProcessor 和 MyBeanPostProcessor 的修改效果
@Service
public class WorldService {
private String message;
public WorldService() {
this.message = "World, Spring!";
}
public WorldService(String message) {
this.message = message;
}
public void sayWorld() {
System.out.println(message);
}
}
- MyNewBean:用于测试 MyBeanDefinitionRegistryPostProcessor 和 MyInstantiationAwareBeanPostProcessor 的创建和修改效果
public class MyNewBean {
private String message;
public MyNewBean() {
this.message = "This is a new bean!";
}
public MyNewBean(String message) {
this.message = message;
}
public void saySomething() {
System.out.println(message);
}
}
- TestController:用于测试各个 bean 的实际表现
@RestController
public class TestController {
@Autowired
private HelloService helloService;
@Autowired
private WorldService worldService;
@Autowired
private MyNewBean myNewBean;
@GetMapping("/test")
public String test() {
helloService.sayHello();
worldService.sayWorld();
myNewBean.saySomething();
return "Test done!";
}
}
最后,我们可以运行 Spring Boot 项目,并访问 http://localhost:8080/test ,观察控制台的输出,以及各个后置处理器的执行顺序和作用。我们可以看到以下结果:
MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
MyBeanFactoryPostProcessor.postProcessBeanFactory
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation: helloService
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation: worldService
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation: worldService
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues: worldService
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization: worldService
MyBeanPostProcessor.postProcessBeforeInitialization: worldService
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization: worldService
MyBeanPostProcessor.postProcessAfterInitialization: worldService
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation: myNewBean
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization: myNewBean
MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization: myNewBean
Modified by postProcessBeforeInitialization
Modified by postProcessPropertyValues and postProcessAfterInitialization
Modified by postProcessBeforeInitialization
Test done!
从上面的结果可以看出,这四个后置处理器的执行顺序和作用如下:
- MyBeanDefinitionRegistryPostProcessor:最先执行,在所有的 bean 定义被加载后,创建并注册了一个名为 myNewBean 的新的 bean 定义,并修改了 helloService 的 scope 为 prototype。
- MyBeanFactoryPostProcessor:其次执行,在所有的 bean 定义被加载后,修改了 worldService 的 lazyInit 为 true。
- MyInstantiationAwareBeanPostProcessor:第三执行,在每个 bean 实例化和初始化的过程中,修改或者增强 bean 的对象和属性。它的 postProcessBeforeInstantiation 方法返回了一个非空对象,导致 myNewBean 的实例化过程被跳过。它的 postProcessAfterInstantiation 方法返回了 false,导致 helloService 的属性注入过程被跳过。它的 postProcessPropertyValues 方法返回了一个非空属性值,导致 worldService 的 message 属性被修改。它的 postProcessBeforeInitialization 方法返回了一个非空对象,导致 myNewBean 的初始化结果被修改。
- MyBeanPostProcessor:最后执行,在每个 bean 初始化的过程中,修改或者增强 bean 的对象。它的 postProcessBeforeInitialization 方法返回了一个非空对象,导致 helloService 的初始化结果被修改。它的 postProcessAfterInitialization 方法返回了一个非空对象,导致 worldService 的最终结果被修改。