spring 源码 aop 代理执行过程(三)

1 aop 代理如何执行的?

前两编主要分析代理是怎么创建,而且整过分析过程还是比较粗线条分析,真要非常详细分析估计用两编去写远远还是不够的,因为细节的内容实际太多了。另外我身有些细节我也不太理解。我通常比较关心整体的原理,然后慢慢深入分析,如果一开始就深入太多细节,恐怕很容易被绕进去出来。

2 cglib代理分析

直接debug进入代理
这里写图片描述
由上面的截图,很明显当前使用的是cglib的代理,也看到上一编曲在创建cglib 代理创建的那几个拦截器,下面f5进去代理方法testAAA里面,发现进入的是第一个拦截器
这里写图片描述

private class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
    //advisor信息
    private final AdvisedSupport advised;
    public DynamicAdvisedInterceptor(AdvisedSupport advised) {
        this.advised = advised;
    }
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Class<?> targetClass = null;
        Object target = null;
        try {
            //目标对象内部的自我调用将无法实施切面中的增强,
            //<aop:aspect-autoproxy expose-proxy = "true"/>
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            // May be null. Get as late as possible to minimize the time we
            // "own" the target, in case it comes from a pool...
            target = getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }
            //获取得当前拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            // Check whether we only have one InvokerInterceptor: that is,
            // no real advice, but just reflective invocation of the target.
            //如果拦截链为空,则仅仅是通过反身调用目标
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                //没有任何advice 相当直接调用目标
                retVal = methodProxy.invoke(target, argsToUse);
            } else {
                // We need to create a method invocation...
                //传入拦截链路,创建Invocation,然后调用proceed();
                retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
            }
            //处理返回值
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        } finally {
            if (target != null) {
                releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
    //省略一些代码
}

这里写图片描述

CglibMethodInvocation.proceed 处理拦截调用链

    @Override
    public Object proceed() throws Throwable {
        //  We start with an index of -1 and increment early.
        //currentIndex 从-1开始递增,直到调用完所有拦截器,再调用连接点
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            //调用interceptor,传入自身,以便拦截器回调自身的procced方法
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

    //调用连接点
    @Override
    protected Object invokeJoinpoint() throws Throwable {
            if (this.publicMethod) {
                //调用目标方法
                return this.methodProxy.invoke(this.target, this.arguments);
            }
            else {
                //通过父类调用目标方法
                return super.invokeJoinpoint();
            }
        }

上面截图可以看到两拦截器

public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
    //省略部分代码
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        MethodInvocation oldInvocation = invocation.get();
        invocation.set(mi);
        try {
            return mi.proceed();
        }
        finally {
            invocation.set(oldInvocation);
        }
    }
//省略部分代码

}

MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    //省略一些代码
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        //执行前置方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        //继续执行下个拦截器
        return mi.proceed();
    }

}

AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice, Serializable {
    //省略一些代码
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            //继续执行下一个拦截器
            return mi.proceed();
        }
        finally {
            //调用后置advice
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }
    //省略一些代码
}

3 jdk代理分析

了解jdk动态代理应该都知道,jdk动态代理是利用目标类的接口去创建代理类的;换句话来说就是jdk动态代理的目标类必须实现一个接口;上面的demo目标类不太适用于此;再弄一个测试接口及目标类
这里写图片描述
其实jdk aop的代理过程与cglib代理差别并是不是很大,我们都知道jdk动态代理回调接口为InvocationHandler,而cglib的回调接口为MethodInterceptor,其主要差别就在两者口的实现上,后面的拦截过程是一样的;下来看一下jdk 代理的InvocationHandler invoke方法的实现JdkDynamicAopProxy

    @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 {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 这一段代码跟cglib那边的实现是一样的,获取匹配的调用拦截链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            if (chain.isEmpty()) {

                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                //上面大部分代码跟cglib的一样
                //下面该类是cglib里用的CglibMethodInvocation的父类,内容基本是一样的
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                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);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

到这里spring aop代理的实现原理基介绍完了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值