Spring Aop原理分析(一) - 建立AopProxy代理对象

Aop基础知识准备

在开始Aop原理分析之前,必须先两个知识点:

  1. Aop基础:http://sishuok.com/forum/blogPost/list/2466.html
  2. 代理模式:http://www.cnblogs.com/machine/archive/2013/02/21/2921345.html,重点理解Java动态代理

有了这两个知识点就可以开始我们的Spring Aop源码之旅了,其实Spring Aop是对Java动态代理的增强,添加了通知链、拦截器等功能

AopProxy的生成方式

在Spring的Aop模块中,一个主要的部分是代理对象的生成,即AopProxy的生成,AopProxy类似于Java动态代理的Proxy,有两种方式生成AopProxy,下面看两张类图:

  • 第一种方式,最顶层是ProxyConfig是一个数据,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性;在另一个基类AdvisedSupport的实现中,封装了Aop对通知和通知器的相关操作,这些操作对于不同的Aop的代理对象的生成都是一样的,但对于具体的Aop代理对象的创建,AdvisedSupport把它交给它的子类们去完成;对于ProxyCreatorSupport,可以将它看成是其子类创建Aop代理对象的一个辅助类;具体的Aop代理对象的生成,根据不同的需要,分别由ProxyFactoryBean、ProxyFactory、AspectJProxyFactory来完成
    Spring Aop原理分析(一) - 建立AopProxy代理对象_第1张图片
  • 第二种方式,Aop提供了一种BeanPostProcessor(在IoC容器初始化中有介绍)的方式AbstractAutoProxyCreator,相比第一种方式,当系统比较复杂或者中需要进行aop织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量,同时由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加,并且很多时候可维护性不强,这样的情况下,自动Aop代理的方式就能发挥它巨大的优势了。

本文着重分析自动Aop代理

AopProxy的生成过程

在Tomcat启动时,只要用了Aop的地方就会为目标对象生成AopProxy代理对象,看下Aop生成过程的时序图
Spring Aop原理分析(一) - 建立AopProxy代理对象_第2张图片
由图可知,AopProxy代理对象是在Bean初始化时生成的,其中AbstractAutoProxyCreator中有两个方法:一个是getAdvicesAndAdvisorsForBean(),该方法非常重要,会返回所有的advices(读取BeanDefinition,返回用到Aop的方法的相关信息);另一个是createProxy(),也就是创建代理对象,如果targetClass.isInterface()就创建JdkDynamicAopProxy(通过Proxy.newProxyInstance()),否则创建CglibAopProxy

接下来我们分别分析JdkDynamicAopProxy和CglibAopProxy

JDK创建AopProxy代理对象

JDK创建的Aop代理对象即JdkDynamicAopProxy,上文也提到创建JdkDynamicAopProxy通过Proxy.newProxyInstance(),该方法需要指明三个参数,一个是类装载器,一个是代理接口,另外一个是就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口,这个InvocationHandler接口定了invoke方法,提供代理对象的回调入口,也就是真正调用目标对象的地方

//JdkDynamicAopProxy
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

JdkDynamicAopProxy本身实现了InvocationHandler接口,我们继续看它的invoke方法

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Class<?> targetClass = null;
        Object target = null;

        try {
        ......

            Object retVal;

            // 获取拦截器链来获取advices链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 通过拦截器->通知
                retVal = invocation.proceed();
            }

            ......
        }
    }

CGLIB创建AopProxy代理对象

CglibAopProxy和JdkDynamicAopProxy不太一样,是通过Enhancer对象生成代理对象的,CglibAopProxy.getProxy()有两个方法比较重要:

  • getCallbacks(),需要注意的是Enhancer通过callback回调目标对象,在Enhancer的callback回调过程中,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成Aop功能的

即Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);//advised即类AdvisedSupport
有没有觉得this.advised很熟悉,JdkDynamicAopProxy中也出现过advised,就是说通知通过拦截器被增强了

  • createProxyClassAndInstance(),创建代理对象

总结

返回的代理对象也就是Bean,包装了真Bean的Bean

你可能感兴趣的:(java,spring,源码,互联网,spring-aop)