Spring AOP原理之拦截器调用的实现

接上文 Spring AOP原理之建立AopProxy代理对象

在Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调来完成的。如果使用JDK的Proxy来生成代理对象,那么需要通过InvocationHandler来设置拦截器回调.而如果使用CGLIB来生成代理对象,就需要根据CGLIB的使用要求.通过DynamicAdvisedlnterceptor来完成回调。

JdkDynamicAopProxy的invoke拦截

上篇文章中,在JdkDynamicAopProxy生成代理对象的时候,我们可以看到这样的源码:


   //调用JDK生成代理对象
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

这里的this参数对应的是InvocationHandler对象,InvocationHandlerJDK定义的反射类的一个接口,这个接口定义了invoke方法。

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

而这个invoke方法是作为JDK Proxy代理对象进行拦截的回调入口出现的。在JdkDynamicAopProxy中实现TlnvocationHandler接口,也就是说当Proxy对象的代理方法被调用时.JdkDynamicAopProxyinvoke方法作为Proxy对象的回调函数被触发,从而通过invoke的其体实现。来完成对目标对象方法调用的拦截或者说功能增强的工作。

JdkDynamicAopProxy实现的该方法如下:


  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        Object var13;
        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {

                //如果目标对象没有实现Object类的基本方法:equals
                Boolean var19 = this.equals(args[0]);
                return var19;
            }

            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                //如果目标对象没有实现Object类的基本方法:hashCode
                Integer var18 = this.hashCode();
                return var18;
            }

            if (method.getDeclaringClass() == DecoratingProxy.class) {
                //
                Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
                return var17;
            }

            Object retVal;
            if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                //根据代理对象的配置来调用服务
                retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                return retVal;
            }

            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            //得到目标对象
            target = targetSource.getTarget();
            Class targetClass = target != null ? target.getClass() : null;
            //获得定义好的拦截器链
            List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            //如果没有设置拦截器,那么久直接调用target的对应方法
            if (chain.isEmpty()) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            } else {
                //如果有定义拦截器,就先调用拦截器之后,再调用目标对象的对应方法
                MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                //沿着拦截器继续前进
                retVal = invocation.proceed();
            }

            Class returnType = method.getReturnType();
            if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
            }

            var13 = retVal;
        } finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }

            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }

        }

        return var13;
    } 
  

Proxy对象的代理设里是在invoke方法中完成的.这些设里包括获取目标对象、拦截器链.同时把这些对象作为愉入,创建了ReflectiveMethodlnvocation对象,通过这个ReflectiveMethodlnvocation对象来完成对AOP功能实现的封装。在这个invoke方法中,包含了一个完整的拦截器链对目标对象的拦截过程。比如获得拦截器链并对拦截器链中的拦截器进行配置,逐个运行拦截器链里的拦截增强,直到最后对目标对象方法的运行等。

CglibAopProxy的intercept拦截

CgIibAopProxyintercept回调方法的实现和JdkDynamicAopProxy的回调实现是非常类似的,只是在CghibAopProxy中构造DynamicAdvisedInterceptor对象来完成拦截器链的调用,而在JdkDynamicAopProxy中是通过构造ReflectiveMethodInvocation对象来完成这个功能的。

DynamicAdvisedInterceptor通过实现MethodInterceptor接口来完成:

import java.lang.reflect.Method;

public interface MethodInterceptor extends Callback {
    Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}

其实现如下:

  public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();

            Object var16;
            try {
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                //得到目标对象
                target = targetSource.getTarget();
                Class targetClass = target != null ? target.getClass() : null;
                //从advised中取得配置好的AOP通知
                List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                //如果没有AOP遨知配里。那么直接调用target对象的调用方法
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = methodProxy.invoke(target, argsToUse);
                } else {
                //通过CglibMethodlnvocation来启动advice通知
                    retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
                }

                retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
                var16 = retVal;
            } finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }

                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }

            }

            return var16;
        } 
  

从上面可以看出,拦截器的实现逻辑是一样的。包括目标对象的调用,AOP拦截器链的调用以及配置通知器等。

你可能感兴趣的:(spring源码初探)