Spring中JDK动态代理和CBLIB代理的拦截逻辑原理

// 这个是JDK代理的拦截逻辑,JdkDynamicAopProxy实现了InvocationHandler
// 从这个类获取的代理对象执行的就是该类的invoke方法
// Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
    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;
        try {
            // 如果执行的是equals方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                return equals(args[0]);
            }
            // 处理hashCode方法
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                return hashCode();
            }
            // 如果方法所在的类是DecoratingProxy类型,装饰代理类型
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // 执行接口的方法
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            // this.advised.opaque默认为false,见setOpaque方法
            // 设置是否阻止通过此配置创建的代理被强制转换为Advised对象来查询代理状态,默认值是"false",这意味着任何AOP代理都可以被强制转换为Advised对象
            // 也就是当this.advised.opaque默认值为false的情况下(Advised (proxy))是正确的
            // 这是是处理特殊情况,类型为Advised就不需要走代理逻辑
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // 直接执行目标方法
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }
            // 方法执行返回值
            Object retVal;
            // 是否需要暴露代理对象
            // this.advised是一个代理对象的配置类
            if (this.advised.exposeProxy) {
                // 将新代理对象设置到ThreadLocal中,并将老的代理对象保存
                oldProxy = AopContext.setCurrentProxy(proxy);
                // 标记设置了代理对象上下文
                setProxyContext = true;
            }
            // 获取目标对象
            target = targetSource.getTarget();
            // 获取目标对象的class
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 获取此方法的拦截链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            {
                // 获取方法缓存的拦截器链
                MethodCacheKey cacheKey = new MethodCacheKey(method);
                List<Object> cached = this.methodCache.get(cacheKey);
                // 如果没有被缓存
                if (cached == null) {
                    // 获取拦截器和通知
                    cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
                    {
                        // 获取全局的切面适配器注册表
                        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
                        {
                            public DefaultAdvisorAdapterRegistry() {
                                registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
                                registerAdvisorAdapter(new AfterReturningAdviceAdapter());
                                registerAdvisorAdapter(new ThrowsAdviceAdapter());
                            }
                        }
                        // 获取到设置的可用切面,Advisor对象是一个(切点 + 一个通知)的低级切面
                        Advisor[] advisors = config.getAdvisors();
                        // 有多少个切面就有多少个拦截器
                        List<Object> interceptorList = new ArrayList<>(advisors.length);
                        // 获取到真实类型
                        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
                        // 是否存在IntroductionAdvisor这种切面
                        Boolean hasIntroductions = null;
                        // 遍历所有的切面
                        for (Advisor advisor : advisors) {
                            // 如果是切点类型的切面PointcutAdvisor
                            if (advisor instanceof PointcutAdvisor) {
                                // 强转
                                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                                // 如果需要预过滤,使用类过滤器进行过滤该类是否可以用
                                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                                    // 类可用,就获取方法匹配器
                                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                                    boolean match;
                                    // 如果是匹配器是IntroductionAwareMethodMatcher这种类型
                                    if (mm instanceof IntroductionAwareMethodMatcher) {
                                        // 是否存在可用的IntroductionAdvisor这种切面
                                        if (hasIntroductions == null) {
                                            hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                                            {
                                                // 遍历所有的切面,找到该IntroductionAdvisor的匹配器来处理,如果能匹配上
                                                // 表示有可用的IntroductionAdvisor
                                                for (Advisor advisor : advisors) {
                                                    if (advisor instanceof IntroductionAdvisor) {
                                                        IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                                                        if (ia.getClassFilter().matches(actualClass)) {
                                                            return true;
                                                        }
                                                    }
                                                }
                                                return false;
                                            }
                                        }
                                        // 使用匹配器进行匹配
                                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                                    } else {
                                        // 否则使用普通的方法匹配器进行匹配
                                        // 这个是根据不同的实现进行规则进行匹配
                                        match = mm.matches(method, actualClass);
                                    }
                                    // 如果匹配到可用的切面
                                    if (match) {
                                        // 从全局的切面适配器注册表中获取符合该切面的拦截器
                                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                                        {
                                            List<MethodInterceptor> interceptors = new ArrayList<>(3);
                                            // 获取到切面的通知
                                            Advice advice = advisor.getAdvice();
                                            // 如果通知是MethodInterceptor方法拦截器类型
                                            if (advice instanceof MethodInterceptor) {
                                                // 保存起来
                                                interceptors.add((MethodInterceptor) advice);
                                            }
                                            // 如果是其他类型的通知,使用适配器来适配成MethodInterceptor类型
                                            for (AdvisorAdapter adapter : this.adapters) {
                                                if (adapter.supportsAdvice(advice)) {
                                                    // MethodBeforeAdviceAdapter
                                                    return (advice instanceof MethodBeforeAdvice);
                                                    // AfterReturningAdviceAdapter
                                                    return (advice instanceof AfterReturningAdvice);
                                                    // ThrowsAdviceAdapter
                                                    return (advice instanceof ThrowsAdvice);
                                                }
                                                {
                                                    interceptors.add(adapter.getInterceptor(advisor) {
                                                    // MethodBeforeAdviceAdapter
                                                    MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
                                                    return new MethodBeforeAdviceInterceptor(advice);
                                                    // AfterReturningAdviceAdapter
                                                    AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
                                                    return new AfterReturningAdviceInterceptor(advice);
                                                    // ThrowsAdviceAdapter
                                                    return new ThrowsAdviceInterceptor(advisor.getAdvice());
                                                });
                                                }
                                            }
                                            // 如果没有拦截器,表示这个切面有问题,无法处理成MethodInterceptor类型的通知
                                            if (interceptors.isEmpty()) {
                                                throw new UnknownAdviceTypeException(advisor.getAdvice());
                                            }
                                            // 返回
                                            return interceptors.toArray(new MethodInterceptor[0]);
                                        }
                                        // 是否是动态匹配
                                        if (mm.isRuntime()) {
                                            // 遍历找到的所有拦截器,封装成InterceptorAndDynamicMethodMatcher对象
                                            // 动态匹配是需要在运行的时候匹配该拦截器是否可用
                                            // 有多少个拦截器,则添加多少组拦截器与匹配器组
                                            for (MethodInterceptor interceptor : interceptors) {
                                                // 添加动态方法匹配器
                                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                            }
                                        } else {
                                            // 否则是静态匹配
                                            // 保存所有的MethodInterceptor通知的集合
                                            interceptorList.addAll(Arrays.asList(interceptors));
                                        }
                                    }
                                }
                            }
                            // 如果切面是IntroductionAdvisor这种类型,详见类级别的切面IntroductionAdvisor
                            else if (advisor instanceof IntroductionAdvisor) {
                                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                                // 如果需要预过滤,使用类过滤器进行过滤该类是否可以用
                                if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                                    // 如果IntroductionAdvisor切面可用,获取切面的拦截器,上面有详细讲
                                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                                    interceptorList.addAll(Arrays.asList(interceptors));
                                }
                            } else {
                                // 其他类型的切面,上面有俩同的代码,详细讲过
                                Interceptor[] interceptors = registry.getInterceptors(advisor);
                                interceptorList.addAll(Arrays.asList(interceptors));
                            }
                        }

                        return interceptorList;
                    }
                    // 缓存起来
                    this.methodCache.put(cacheKey, cached);
                }
                return cached;
            }
            // 如果未找到了拦截器
            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();{
                    // currentInterceptorIndex=-1
                    // interceptorsAndDynamicMethodMatchers传递的所有拦截器
                    // 只有没有interceptorsAndDynamicMethodMatchers的时候,执行目标方法
                    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                        // 执行目标方法
                        return invokeJoinpoint();
                    }
                    // 开始执行拦截器
                    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
                    // 如果拦截器类型为InterceptorAndDynamicMethodMatcher类型,需要表示动态匹配
                    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                        // 需要动态匹配的情况下是到执行的时候才会进行匹配拦截器
                        InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                        // 获取目标类
                        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                        // 使用方法匹配器进行匹配,这个逻辑上面已经讲过了
                        // 当需要动态匹配的时候,dm中保存了interceptor和methodMatcher匹配器,如果匹配,那么对应的拦截器可用
                        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                            // 运行的时候匹配成功,执行对应的拦截器
                            return dm.interceptor.invoke(this);
                        }
                        else {
                            // 动态匹配该拦截器不可用,继续执行下一个拦截器
                            // 递归执行当前方法
                            return proceed();
                        }
                    }
                    // 如果不是InterceptorAndDynamicMethodMatcher这种类型,那么剩下的就是MethodInterceptor的拦截器了
                    else {
                        // 强转为MethodInterceptor拦截器,执行拦截器的方法
                        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
                    }
                }
            }
            // 获取到方法的返回值
            Class<?> returnType = method.getReturnType();
            // 如果方法的返回值类型是当前类的类型,就将代理对象返回
            if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            }
            // 如果返回值不为Void,并且返回类型写的简单类型,null是无法赋值的,那么抛出异常
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException();
            }
            // 返回执行结果
            return retVal;
        } finally {
            // targetSource用完就需要释放
            if (target != null && !targetSource.isStatic()) {
                // 释放所属当前目标类的targetSource
                targetSource.releaseTarget(target);
            }
            // 如果暴露的当前线程的代理对象,执行完需要还原成原来的对象
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}
// 这个是CGLIB的拦截逻辑,创建CGLIB代理对象的时候,会将这个拦截器放在第一位,控制所有的拦截器的执行
// 在创建CGLIB代理的时候,会创建多个Callback增强对象
// Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// enhancer.setCallbacks(callbacks);

class DynamicAdvisedInterceptor implements MethodInterceptor{
    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();
        try {
            // 是否需要暴露代理对象
            // this.advised是一个代理对象的配置类
            if (this.advised.exposeProxy) {
                // 将新代理对象设置到ThreadLocal中,并将老的代理对象保存
                oldProxy = AopContext.setCurrentProxy(proxy);
                // 标记设置了代理对象上下文
                setProxyContext = true;
            }
            // 获取目标对象
            target = targetSource.getTarget();
            // 获取目标对象的class
            Class<?> targetClass = (target != null ? target.getClass() : null);
            // 获取此方法的拦截链,上面将JDK代理的时候有完全一样的解释
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            // 方法执行返回值
            Object retVal;
            // 如果方法是public,并且没有拦截器链
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                // 适配方法参数
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                // 执行目标方法
                retVal = methodProxy.invoke(target, argsToUse);
            }
            else {
                // 创建一个CBLIB的方法调用对象,内部控制了拦截器的执行
                // CglibMethodInvocation继承了ReflectiveMethodInvocation
                MethodInvocation invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
                retVal = invocation.proceed();{
                    // 详细的见上面的JDK代理的逻辑
                    return super.proceed();
                }
            }
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        }
        finally {
            // targetSource用完就需要释放
            if (target != null && !targetSource.isStatic()) {
                // 释放所属当前目标类的targetSource
                targetSource.releaseTarget(target);
            }
            // 如果暴露的当前线程的代理对象,执行完需要还原成原来的对象
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值