BeanPostProcessor提供了在bean初始化之前和之后插入自定义逻辑的能力。与BeanFactoryPostProcessor的区别是处理的对象不同,BeanFactoryPostProcessor是对beanfactory进行处理,BeanPostProcessor是对bean进行处理。
BeanPostProcessor接口概述
Spring中使用了许多BeanPostPorcessor来处理回调,在了解Spring Bean的生命周期时,会发现充斥着许多BeanPostProcessor的方法执行.了解这些Spring框架的BeanPostProcessor,来试图找到一些AOP有关的线索。
从整体的视角来看,Spring IoC支持以注解驱动的方式来创建与管理对象,那么Spring AOP是用来代理对象的,没有了对象,空谈Spring AOP是无意义的。在前面分析getBean的流程中,我们也找到了一些AOP的蛛丝马迹,下面我们从BeanPostcessor的角度来看看在Bean的生命周期中一些关键的后置处理器。
在IOC过程中引入AOP
AOP核心实现-动态代理。大家都知道,Spring AOP是基于动态代理实现的,那么什么是动态代理呢,其实就是一种通过实现或继承的方式对原来类的某些功能进行增强的技术,JDK中动态代理的实现方式是这样的:
Class[] interfaces = bean.getClass().getInterfaces();
Object obj = Proxy.newProxyInstance(AopPostProcessor.class.getClassLoader(), interfaces, new AopInvocationHandler(bean));
public class AopInvocationHandler implements InvocationHandler {
Object target;
public AopInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before proxy");
Object obj = method.invoke(target, args);
System.out.println("after proxy");
return obj;
}
很简单,也很直观,其实也不过是通过InvocationHandler在方法执行前后增加了一些处理过程。而基于Cglib的也是一样:
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(AopBean.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println("after");
return obj;
}
});
Object enObj = enhancer.create();
((AopBean)enObj).getName();
这就是动态代理,如果想要对哪个类进行增强,直接通过这两种方式就可以了,但是为什么还要出一个面向切面编程呢?那和IOC又有什么关系呢?我们接下来就要想了,要对单个的类增强用以上方式是比较容易了,但是如果是批量的呢?我们总不能每一个类都写一个代理吧!那么我们就需要一种批量处理的方式了,其实说到批量处理,用模板模式来解决是最适合的方式了。但是在Spring框架中所有的类及Bean实例都是由Spring IOC来管理的,那么这种批量的模板式的处理也必须要基于Spring IOC来完成了。
AOP切面实现-BeanPostProcessor。其实前面在分析Spring IOC源码时有一个方法已经标记出来时让大家记住的,就是postProcessBeanFactory,并且告诉了大家这是自定义扩展的位置,而今天AOP的接入就是依赖这种方式实现的。在Spring中有一个接口BeanPostProcessor, 我们只要实现了这个接口中的方法postProcessBeforeInitialization或postProcessAfterInitialization,在方法中创建Bean的代理并且以李代桃僵的方式用代理对象替换了原来的实际对象,那么就会被自动注册为Bean,这样我们通过Spring IOC获取Bean对象并且调用的时候,实际调用的就是代理对象,增强功能自然也就实现了。要形成切面,其实就是对多个Bean的批量代理,因为每次初始化的时候都会自动调用postProcessBeforeInitialization或postProcessAfterInitialization,我们只要控制好Bean的范围就可以形成一个个的切面了。
综上所述,我们通过实现BeanPostProcessor接口实现切面;通过在切面中的动态代理返回代理对象实现功能增强。Spring面向切面编程也就可以实现了。当然还会有许多其他的辅助过程,但是只要记住在哪里形成切面和如何通过动态代理增强特定功能这两点核心就可以了。