BeanPostProcessor是Bean的后置处理器,它可以监听容器触发的事件。
BeanPostProcessor是一个接口类,它有两个接口方法: postProcessBeforeInitialization(Object bean, String beanName),在Bean的初始化前提供回调入口;另一个是postProcessAfterInitialization(Object bean, String beanName),在Bean的初始化后提供回调入口。
BeanPostProcessor实现原理
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
之前在介绍AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])
时,你一定注意到这样的几行代码
//完成bean的依赖注入
populateBean(beanName, mbd, instanceWrapper);
//到这里bean的生成和依赖注入已经完成了,这个方法开始对bean进行初始化
//初始化过程包含了对Bean的后置处理器BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法的调用
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
以下是Spring源码中对bean进行初始化的逻辑。从源码中我们可以看到是先通过applyBeanPostProcessorsBeforeInitialization()方法使用注册的BeanPostProcessor的postProcessBeforeInitialization()方法依次回调,然后是通过invokeInitMethods()方法依次调用当前bean对应的初始化方法,再通过applyBeanPostProcessorsAfterInitialization方法使用注册的BeanPostProcessor的postProcessorAfterInitialization()方法依次进行回调。
AbstractAutowireCapableBeanFactory.initializeBean(String, Object, RootBeanDefinition)
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
//对Bean的后置处理器BeanPostProcessor的postProcessBeforeInitialization方法的调用
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用bean的初始化方法,初始化方法通过inti-method属性指定。
//如果bean实现了InitializingBean接口,那么bean的afterPropertiesSet()实现也会被调用
if (wrappedBean != null) {
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//对Bean的后置处理器BeanPostProcessor的postProcessAfterInitialization方法的调用
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
}
return wrappedBean;
}
- 实例化Bean
- 调用BeanPostProcessor的postProcessBeforeInitialization方法
- 调用bean实例的初始化方法
- 调用BeanPostProcessor的postProcessAfterInitialization方法
BeanPostProcessor示例
BeanPostProcessor的使用非常简单,只需要通过实现接口类BeanPostProcessor设计一个具体的后置处理器,然后将其添加到Bean配置文件中。
首先定义Bean。
public class MyBean {
}
实现后置处理器。
public class MyBeanPostPrcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("对象" + beanName + "开始实例化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("对象" + beanName + "实例化完成");
return bean;
}
}
将定义的Bean和后置处理器添加到Bean配置文件
<?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-2.5.xsd">
<bean id="myBean" class="container.MyBean"></bean>
<bean class="container.MyBeanPostPrcessor"></bean>
</beans>
测试。
public class MyBeanPostPrcessorTest {
@Test
public void test1() {
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("MyBean.xml"));
MyBeanPostPrcessor beanPostProcessor = new MyBeanPostPrcessor();
bf.addBeanPostProcessor(beanPostProcessor);
bf.getBean("myBean");
}
@Test
public void test2() {
AbstractApplicationContext aac = new ClassPathXmlApplicationContext("MyBean.xml");
aac.getBean("myBean");
}
}
分别运行test1方法和test2方法。结果分别为
对象myBean开始实例化
对象myBean实例化完成
BeanFactory和ApplicationContext对待bean后置处理器的不同
观察test1和test2方法的实现,你会发现BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它。而使用BeanFactory实现的时候,bean后置处理器必须显式地去注册.
多个BeanPostProcessor实现的回调顺序
假如我们使用了多个的BeanPostProcessor的实现类,那么如何确定回调顺序呢?
将我们自定义的BeanPostProcessor实现类同时实现Ordered接口,然后Spring将根据Ordered接口定义的getOrder()方法的返回值来决定BeanPostProcessor回调的先后顺序,getOrder()返回值越小的越先进行回调。此外,实现了Ordered接口的BeanPostProcessor总是比没有实现Ordered接口的BeanPostProcessor先进行回调。
public class MyBeanPostPrcessor2 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("对象" + beanName + "开始实例化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("对象" + beanName + "实例化完成");
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
本文已收录于Spring源码札记专栏。