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<Object> 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<Object> 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拦截器链的调用以及配置通知器等。

    原文作者:AOP
    原文地址: https://blog.csdn.net/She_lock/article/details/80333987
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞