Spring5源码13-AOP源码分析(下)创建代理和执行过程

首先我们需要知道的是,调用这个方法的是 createAopProxy() 方法的返回值,那么就可能是JdkDynamicAopProxy.getProxy 或者 ObjenesisCglibAopProxy.getProxy。下面我们来详细分析一下代理生成的过程。

5. JdkDynamicAopProxy

下面代码省略了JdkDynamicAopProxy 部分无关代码。

对于JDK 动态代理来说,实际调用代理方法是在 java.lang.reflect.InvocationHandler#invoke 中,因此 JdkDynamicAopProxy#invoke是我们的重点关注对象。

5.1 JdkDynamicAopProxy#getProxy

@Override
public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
复制代码

5.2 JdkDynamicAopProxy#invoke

@Override
@Nullable
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)) {
                        // The target does not implement the equals(Object) method itself.
                        return equals(args[0]);
                }
                // 处理 hashCode 方法
                else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                        // The target does not implement the hashCode() method itself.
                        return hashCode();
                }
                // 处理 DecoratingProxy 类
                else if (method.getDeclaringClass() == DecoratingProxy.class) {
                        // There is only getDecoratedClass() declared -> dispatch to proxy config.
                        return AopProxyUtils.ultimateTargetClass(this.advised);
                }
                // 处理 Class类的isAssignableFrom(Class cls) 方法
                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;
                }

                // Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);

                // Get the interception chain for this method.
                //  获取当前方法的拦截链路,其中包括将AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice 转换成合适的类型(InterceptorAndDynamicMethodMatcher)
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);


                if (chain.isEmpty()) {
                        // 拦截链路为空则直接调用切点方法
                        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                        retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                else {
                        // We need to create a method invocation...
                        // 否则构建一个新的 方法调用对象 ReflectiveMethodInvocation
                        // 以便于使用proceed 方法进行链接表用拦截器
                        MethodInvocation invocation =
                                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                        // Proceed to the joinpoint through the interceptor 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);
                }
        }
}
复制代码

上面我们有两个方法需要注意:

  • List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);。这一句将 获取当前方法的拦截链路,其中包括将AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice 转换成 拦截器,用于后面的调用。

  • retVal = invocation.proceed(); : 对增强方法的调用

5.2.1 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

我们讲了在 InstantiationModelAwarePointcutAdvisorImpl 中,Spring根据Aspect系列注解的不同将方法封装成了不同的Advice :AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice

invocation.proceed() 的分析中我们会发现最终调用的增强方法为 MethodInterceptor#invoke方法。但是在上述五个Advice 中,只有AspectJAroundAdviceAspectJAfterAdvice 实现了MethodInterceptor 接口,其余的并没有实现 MethodInterceptor 接口,那么这时候就需要进行一个转换,将 Advice 转换成 MethodInterceptor 类型,该转换就是在此方法中完成。

由于 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 方法最终会调用DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice,所以我们这里直接看该方法

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, @Nullable Class<?> targetClass) {

        // This is somewhat tricky... We have to process introductions first,
        // but we need to preserve order in the ultimate list.
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;

        for (Advisor advisor : advisors) {
                // 我们这里的Advisor 都是 PointcutAdvisor 所以这里只分析该内容
                if (advisor instanceof PointcutAdvisor) {
                        // Add it conditionally.
                        PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

                        if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                                boolean match;
                                if (mm instanceof IntroductionAwareMethodMatcher) {
                                        if (hasIntroductions == null) {
                                                hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                                        }
                                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                                }
                                else {
                                        match = mm.matches(method, actualClass);
                                }
                                //如果代理规则与当前类匹配
                                if (match) {
                                        // 进行转化注册
                                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                                        if (mm.isRuntime()) {
                                                // Creating a new object instance in the getInterceptors() method
                                                // isn't a problem as we normally cache created chains.
                                                for (MethodInterceptor interceptor : interceptors) {
                                                        // 封装成 InterceptorAndDynamicMethodMatcher
                                                        interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                                }
                                        }
                                        else {
                                                interceptorList.addAll(Arrays.asList(interceptors));
                                        }
                                }
                        }
                }
                else if (advisor instanceof IntroductionAdvisor) {
                        IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                        if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                                Interceptor[] interceptors = registry.getInterceptors(advisor);
                                interceptorList.addAll(Arrays.asList(interceptors));
                        }
                }
                else {
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                }
        }
        // 返回最终的拦截器集合
        return interceptorList;
}
复制代码

我们可以看到关键的代码就是 registry.getInterceptors(advisor);,所以我们这里来看 DefaultAdvisorAdapterRegistry#getInterceptors 的 实现,其目的是将所有的Advisor中的Advice 转换成 MethodInterceptor

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<>(3);
        Advice advice = advisor.getAdvice();
        // 如果 Advice 就是MethodInterceptor 类型,则直接保存
        if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
        }
        // 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值