1. 概述
BeanPostProcessor 和 Ordered 接口用于在Spring容器初始化Bean的过程中进行自定义处理,并控制处理顺序
2. BeanPostProcessor
BeanPostProcessor 接口允许你在Spring容器初始化Bean的前后对Bean进行自定义处理。它有两个方法:
- postProcessBeforeInitialization(Object bean, String beanName):在Bean初始化之前调用。
- postProcessAfterInitialization(Object bean, String beanName):在Bean初始化之后调用。
- bean:容器正在创建的那个bean的引用;
- beanName:容器正在创建的那个bean的名称;
2.1 bean的生命周期
描述如下:
- 首先由Spring容器创建bean实例;
- 为bean的属性注入值;
- 若bean实现了各类Aware接口,则调用相应的set方法,
- 比如说,实现了BeanNameAware接口的bean,此时容器将调用bean的setBeanName方法,将bean的name作为参数;
- 实现了ApplicationContextAware接口的bean,此时容器将执行bean的setApplicationContext方法,将bean所在的上下文对象作为参数……
- 若容器中包含实现了BeanPostProcessor接口的bean,则此时将调用这些bean的postProcessBeforeInitialization方法,将当前正在创建的bean的引用以及bean的name作为参数传入;
- 若bean实现了InitializingBean接口,此时将调用bean的afterPropertiesSet方法;
- 若bean指定了自定义的初始化方法,比如说通过配置文件的init-method选项,则此时将执行这个自定义初始化方法;
- 若容器中包含实现了BeanPostProcessor接口的bean,则此时将调用这些bean的postProcessAfterInitialization方法,将当前正在创建的bean的引用以及bean的name作为参数传入;
- 可以在一个容器中注册多个不同的BeanPostProcessor的实现类对象,而bean在创建的过程中,将会轮流执行这些对象实现的before和after方法
- 执行顺序通过BeanPostProcessor的实现类实现这个Ordered接口,并实现接口的getOrder方法
- 这个时候,bean就算是初始化完毕,可以被使用了,在容器销毁之前,这个对象将一直保存在容器中;
- 若bean实现了DisposableBean接口,则在容器销毁时,会调用bean的destroy方法;
- 如果bean定义了自定义的销毁方法,则在容器销毁时,会调用这个自定义的销毁方法;
- 容器销毁成功,bean也被回收
2.2 使用注意
2.2.1 BeanPostProcessor依赖的bean,不会执行BeanPostProcessor的方法
当我们在BeanPostProcessor的实现类中,依赖了其他的bean,
那么被依赖的bean被创建时,将不会执行它所在的BeanPostProcessor实现类实现的方法,
比如我们修改PostBean的实现,如下所示:
- 容器在创建User这个bean时,不会执行PostBean实现的两个方法,
- 因为由于PostBean依赖于user,所以user需要在PostBean之前创建完成,
- 这也就意味着在user创建时,PostBean还未初始化完成,所以不会调用它的方法。
@Component
public class PostBean implements BeanPostProcessor, Ordered {
// 让PostBean依赖User
@Autowired
private User user;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
2.2.2 BeanPostProcessor以及依赖的bean无法使用AOP
Spring的AOP代理就是作为BeanPostProcessor实现的
,
所以我们无法对BeanPostProcessor的实现类使用AOP织入通知,
也无法对BeanPostProcessor的实现类依赖的bean使用AOP织入通知。
2.3 将BeanPostProcessor注册到Spring容器中
2.3.1 @Component注解
使用@Component注解:在实现类上添加@Component注解,这样Spring会自动扫描并注册这个bean。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
// 实现方法
}
2.3.2 使用@Bean配置BeanPostProcessor的限制
使用Java配置类:如果你使用的是Java配置类,可以在配置类中注册这个bean。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
示例如下:
/**
* 此BeanPostProcessor的实现类,还实现了Ordered接口
*/
public class PostBean implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("before -- " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("after -- " + beanName);
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
在配置类中,声明PostBean可以有以下几种方式
- 只有第一种和第二种方式,会让Spring容器将PostBean当作BeanPostProcessor处理
- 而第三种方式,则会被当作一个普通Bean处理,实现BeanPostProcessor的两个方法都不会被调用,
- 因为在PostBean的继承体系中,Ordered和BeanPostProcessor是同级别的,
- Spring无法识别出这个Ordered对象,也是一个BeanPostProcessor对象;
- 但是使用PostBean却可以,因为PostBean类型就是BeanPostProcessor的子类型
- 所以,在
使用@Bean声明工厂方法返回BeanPostProcessor实现类对象时,返回值必须是BeanPostProcessor类型,或者更低级的类型
。
@Configuration public class BeanConfig { // 方式1:PostBean @Bean public PostBean postBean() { return new PostBean(); } // 方式2:返回值为BeanPostProcessor @Bean public BeanPostProcessor postBean() { return new PostBean(); } // 方式3:返回值为Ordered @Bean public Ordered postBean() { return new PostBean(); } }
2.3.3 spring.factories
创建 BeanPostProcessor 实现类:
首先,创建一个实现 BeanPostProcessor 接口的类。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
创建自动配置类:创建一个自动配置类,并在其中定义 BeanPostProcessor 的 @Bean 方法
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
创建 spring.factories 文件:在 src/main/resources/META-INF/ 目录下创建 spring.factories 文件,并在其中添加自动配置类的全限定名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
目录结构
src/main/java/
com/example/
MyBeanPostProcessor.java
MyAutoConfiguration.java
src/main/resources/
META-INF/
spring.factories
2.3.4 Xml
在XML中注册这个bean。
<bean id="myBeanPostProcessor" class="com.example.MyBeanPostProcessor"/>
3. Order
Ordered 接口用于控制多个 BeanPostProcessor 的执行顺序。它有一个方法:
- getOrder():返回一个整数值,表示处理器的顺序。值越小,优先级越高。
4. 多个 BeanPostProcessor 的顺序
如果有多个 BeanPostProcessor,可以通过实现 Ordered 接口来控制它们的执行顺序。值越小,优先级越高。
5. 举例
自定义Bean后处理器
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyService) {
System.out.println("Before Initialization: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyService) {
System.out.println("After Initialization: " + beanName);
}
return bean;
}
@Override
public int getOrder() {
return 1; // 优先级,值越小优先级越高
}
}
服务类
import org.springframework.stereotype.Service;
@Service
public class MyService {
public void serve() {
System.out.println("Service method executed");
}
}
主类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
另一个自定义Bean后处理器
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class AnotherBeanPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyService) {
System.out.println("Another Before Initialization: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyService) {
System.out.println("Another After Initialization: " + beanName);
}
return bean;
}
@Override
public int getOrder() {
return 2; // 优先级,值越小优先级越高
}
}
运行示例
Before Initialization: myService
Another Before Initialization: myService
After Initialization: myService
Another After Initialization: myService
Service method executed