( 六 ) Spring Bean 后置处理器-BeanPostProcessor
本文内容纲要:
- - 4、使用示例
( 六 ) Spring Bean 后置处理器-BeanPostProcessor
1、简介
BeanPostProcessor 接口也被称为后置处理器,通过该接口可以自定义调用Bean初始化前后执行的操作方法。
如果我们希望容器中创建的每一个bean
,在创建的过程中可以执行一些自定义的逻辑,那么我们就可以编写一个类,并让他实现 BeanPostProcessor
接口,然后将这个类注册到一个容器中。容器在创建bean
的过程中,会优先创建实现了 BeanPostProcessor
接口的 bean
,然后,在创建其他bean
的时候,会将创建的每一个bean
作为参数,调用BeanPostProcessor
的方法。而BeanPostProcessor
接口的方法,即是由我们自己实现的。下面就来具体介绍一下 BeanPostProcessor
的使用。
2、BeanPostProcessor 接口源码如下:
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
postProcessBeforeInitialization: 在 Bean 实例化、依赖注入后,初始化前调用。(初始化前是指: init-method、InitializingBean、@PostConstruct)
postProcessAfterInitialization : 在 Bean 实例化、依赖注入、初始化都完成后调用。
这两个方法有着相同的参数:
- bean:容器正在创建的那个
bean
的引用; - beanName:容器正在创建的那个
bean
的名称;
3、那这两个方法何时执行呢?
这就涉及到Spring
中,bean
的生命周期了,下图表现了bean
的生命周期:
上图中标红的两个地方就是BeanPostProcessor
中两个方法的执行时机。Spring
容器在创建bean
时,如果容器中包含了BeanPostProcessor
的实现类对象,那么就会执行这个类的这两个方法,并将当前正在创建的bean
的引用以及名称作为参数传递进方法中。这也就是说,BeanPostProcessor
的作用域是当前容器中的所有bean
(不包括一些特殊的bean
,这个后面说)。
当需要添加多个后置处理器实现类时,默认情况下 Spring 容器会根据后置处理器的定义顺序来依次调用。也可以通过实现 Ordered 接口的 getOrder 方法指定后置处理器的执行顺序。该方法返回值为整数,默认值为 0,值越大优先级越低。
4、使用示例
HelloWorld 类代码如下:
public class HelloWorld { private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Message : " + message);
}
public void init() {
System.out.println("Bean正在初始化");
}
public void destroy() {
System.out.println("Bean将要被销毁");
}
}
InitHelloWorld 类代码如下:
public class InitHelloWorld implements BeanPostProcessor, Ordered { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("A Before : " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("A After : " + beanName);
return bean;
}
@Override
public int getOrder() {
return 5;
}
}
需要注意的是: postProcessBeforeInitialization 和 postProcessAfterInitialization 方法返回值不能为 null,否则会报空指针异常或者通过 getBean() 方法获取不到 Bean 实例对象,因为后置处理器从Spring IoC 容器中取出 Bean 实例对象后没有再次放回到 IoC 容器中。
InitHelloWorld2 的代码如下:
public class InitHelloWorld2 implements BeanPostProcessor, Ordered { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("B Before : " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("B After : " + beanName);
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
Beans.xml 代码如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.dw.study.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!" />
</bean>
<!-- 注册处理器 -->
<bean class="com.dw.study.InitHelloWorld" />
<bean class="com.dw.study.InitHelloWorld2" />
</beans>
MainApp 类代码如下:
public class MainApp { public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
context.registerShutdownHook();
}
}
运行结果如下:
B Before : helloWorldA Before : helloWorld
Bean正在初始化
B After : helloWorld
A After : helloWorld
Message : Hello World!
Bean将要被销毁
由运行结果可以看出: postProcessBeforeInitialization 方法是在 Bean 实例化和依赖注入后,自定义初始化方法前执行的。而 postProcessAfterInitialization 方法是在自定义初始化方法后执行的。由于 getOrder 方法返回值越大,优先级越低,所以 InitHelloWorld2 先执行。
5、使用注意事项
5.1、BeanPostProcessor依赖的bean,不会执行BeanPostProcessor的方法
当我们在BeanPostProcessor
的实现类中,依赖了其他的bean
,那么被依赖的bean
被创建时,将不会执行它所在的BeanPostProcessor
实现类实现的方法,如下所示:
@Componentpublic 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;
}
}
此时,容器在创建User
这个bean
时,不会执行PostBean
实现的两个方法,因为由于PostBean
依赖于user
,所以user
需要在PostBean
之前创建完成,这也就意味着在user
创建时,PostBean
还未初始化完成,所以不会调用它的方法。
5.2、BeanPostProcessor以及依赖的bean无法使用AOP
以下是Spring
官方文档中的一段话:
Because AOP auto-proxying is implemented as a
BeanPostProcessor
itself, neitherBeanPostProcessor
s nor the beans they reference directly are eligible for auto-proxying, and thus do not have aspects woven into them.
上面这段话的意思大致是说,Spring
的AOP
代理就是作为BeanPostProcessor
实现的,所以我们无法对BeanPostProcessor的实现类使用AOP织入通知,也无法对BeanPostProcessor的实现类依赖的bean使用AOP织入通知。Spring
的AOP
实现我暂时还没有研究过,所以上面的说AOP
作为BeanPostProcessor
实现的意思我不是特别明白,但是我们现在只需要关注BeanPostProcessor
以及它依赖的bean
都无法使用AOP
这一点。
本文内容总结:,4、使用示例,
原文链接:https://www.cnblogs.com/dw3306/p/15069190.html
以上是 ( 六 ) Spring Bean 后置处理器-BeanPostProcessor 的全部内容, 来源链接: utcz.com/z/362515.html