一、接口介绍
spring提供了一个接口类 BeanPostProcessor,我们称其为后置处理器,作用是在 bean 的实例化的过程中对 bean 进行自定义的包装处理,其提供了两个方法。先看看 BeanPostProcessor 的定义。
public interface BeanPostProcessor{
public abstract Object postProcessBeforeInitialization(Object obj, String s) throws BeansException;
public abstract Object postProcessAfterInitialization(Object obj, String s) throws BeansException;
}
根据类的名称,我们可以猜测两个接口方法执行的位置:
1、在bean初始化之前执行;
2、在bean的初始化之后执行。
二、源码解析
理解其原理以及执行的位置,需要到源码中寻找答案。跟踪创建 bean 的实例的 getBean 方法,层层跟进,在AbstractAutowireCapableBeanFactory 类中,找到了执行方法:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction
@Override public
Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
} else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
如上加粗部分是主要的代码,invokeAwareMethods(beanName, bean)、 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);invokeInitMethods(beanName, wrappedBean, mbd)、invokeInitMethods(beanName, wrappedBean, mbd)、applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)。
1、invokeAwareMethods(beanName, bean),对实现了 aware 接口的 bean 进行特殊的处理,实现aware 接口的 bean 在被初始化后,可以取得一些相对应的资源。比如, applicationAware , beanFactoryAware 等。
2、applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName),后置处理器初始化前方法调用。
3、invokeInitMethods(beanName, wrappedBean, mbd),用于用户初始化方法的调用,如实现了 InitializingBean 接口的 bean ,调用其 afterPropertiesSet 和 用户配置的 init-method 方法的调用。
进入applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)和applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName),查看其源码:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if(result ==null) {
return result;
}
}
return result;
}
三、使用
1、定义接口和实例
publi interface DemoService {
public void sayHello();
}
public interface NameInit {
public void setName(String name);
}
public class DemoServiceImpl implements DemoService,NameInit {
String name;
@Override
public void sayHello() {
System.out.println("hello "+name);
}
@Override
public void setName(String name) {
this.name=name;
}
}
2、定义bean的配置
3、定义一个BeanPostProcessor 实例
凡是继承了NameInit的接口,均实例化,注入name值。此处定义接口一方面是要使用接口中提供的setName方法,另一方面减轻系统压力,防止每个bean都进行注入。
public class NameBeanPostProcessor implements BeanPostProcessor {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof NameInit){
((NameInit)bean).setName(name);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
5、定义bean,注入name的值
6、定义另一个BeanPostProcessor ,仅打印日志
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("正在处理"+beanName); return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("已经处理完成"+beanName);
return bean;
}
}
7、定义bean
8、测试类
public class BeanPostProcessorTest {
public static void main(String[] args) {
ApplicationContext context=new FileSystemXmlApplicationContext("beanpostprocessor.xml");
DemoService demoService=(DemoService) context.getBean("demoService");
demoService.sayHello();
}
}
9、测试结果
正在处理demoService
已经处理完成demoService
hello zhangsan
10、总结
两个方法均在bean实例化期间已经完成;
name属性是根据NameInit接口自动注入;
由于两个方法执行的时间特殊性,所以打印日志和记录时间意义不大,主要还是用于注入属性和完善配置。