Spring AOP - 是如何基于Spring IOC 引入动态代理功能的

302 阅读4分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

IOC和AOP是Spring框架的两大核心,IOC是对Bean的管理,而AOP是对IOC功能的补充与增强,本文主要从实现原理及接入方式两方面介绍AOP是如何基于IOC实现面向切面编程的。

Spring的核心是IOC和AOP,IOC的原理和源码流程前面已经提到了,Spring IOC的源码是Spring体系的基础,是最难也是最需要掌握的,但是开始的时候可以先弄清楚关键点和基本流程,在后续学习其他框架源码时都会用到Spring IOC相关的部分,因为它们都是基于Spring IOC建立起来的。所以可以在学习其他框架的源码过程中会逐步理解Spring IOC源码各个部分的功能,从不同角度的一点点积累,最终还是可以完全弄懂的。今天就对Spring 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源码时有一个方法已经标记出来时让大家记住的(详情请见:blog.csdn.net/a1366208071…, 我们只要实现了这个接口中的方法postProcessBeforeInitialization或postProcessAfterInitialization,在方法中创建Bean的代理并且以李代桃僵的方式用代理对象替换了原来的实际对象,那么就会被自动注册为Bean,这样我们通过Spring IOC获取Bean对象并且调用的时候,实际调用的就是代理对象,增强功能自然也就实现了。要形成切面,其实就是对多个Bean的批量代理,因为每次初始化的时候都会自动调用postProcessBeforeInitialization或postProcessAfterInitialization,我们只要控制好Bean的范围就可以形成一个个的切面了。

综上所述,我们通过实现BeanPostProcessor接口实现切面;通过在切面中的动态代理返回代理对象实现功能增强。Spring面向切面编程也就可以实现了。当然还会有许多其他的辅助过程,但是只要记住在哪里形成切面和如何通过动态代理增强特定功能这两点核心就可以了。

更多信息,关注公众号
在这里插入图片描述