0
点赞
收藏
分享

微信扫一扫

Spring AOP原理分析(六)-- AOP执行流程

目录

一、简介

二、AOP执行流程

三、总结


一、简介

在前面一篇文章中,我们介绍了 AOP 代理的创建过程,那么代理对象是创建出来了,在什么时候使用呢?通知方法又是在何处被调用了?
带着这些问题,我们以前面的AOP示例代码,边调试边介绍AOP代理的方法的完整执行过程。

二、AOP执行流程

先回顾一下前面使用AOP的切面代码:

// @Aspect:告诉Spring这是一个切面类
@Aspect
@Component
public class SimpleAspect {

    // 定义切入点表达式
    @Pointcut("execution(* com.wsh.service..*.*(..))")
    private void pointcut() {
    }

    // 环绕通知
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws InterruptedException {
        String methodName = proceedingJoinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的环绕通知(@Around)...");
        try {
            long startTime = System.currentTimeMillis();
            Object result = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println(methodName + "()方法耗时: " + (endTime - startTime) + "毫秒");
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }

    // 前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的前置通知(@Before)...");
    }

    // 后置通知
    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的后置通知(@After)...");
    }

    // 返回通知
    @AfterReturning("pointcut()")
    public void afterReturning(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行" + methodName + "的后置返回通知(@AfterReturning)...");
    }

}
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("新增用户...");
    }
}

当我们调用了被 AOP 代理的方法时,在本例中就是执行addUser()方法,使用 JDK 动态代理会走到 JdkDynamicAopProxy#invoke 方法,使用 CBLIB 代理会走到 DynamicAdvisedInterceptor#intercept 方法,两者的内容基本一样。

这里就以更常见的 JdkDynamicAopProxy#invoke 方法来介绍。

源码如下:

// org.springframework.aop.framework.JdkDynamicAopProxy.invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    // 1.获取到目标对象,也就是被代理对象的引用
    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);
        }
        // 如果是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;

        // 2. 如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中
        // exposeProxy是通过注解@EnableAspectJAutoProxy(exposeProxy = true)进行指定的,如果配置为true,
        // 则可以使用AopContext.currentProxy()获取到代理对象. 在Spring事务方法自调用的时候经常使用到.
        if (this.advised.exposeProxy) {
            // 将代理对象暴露到ThreadLocal中
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // 3.获得目标对象实例
        target = targetSource.getTarget();

        // 获取目标对象的类型
        Class<?> targetClass = (target != null ? target.getClass() : null);

        // 4.获得目标方法对应的拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // 5.如果对应的拦截器链为空,也就是没有可以应用到此方法的通知(Interceptor),则直接通过反射方式进行调用 ==> method.invoke(target, args)
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        } else {
            // 6.如果拦截器链不为空,则需要创建一个MethodInvocation(方法调用对象)
            MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 调用其proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法
            retVal = invocation.proceed();
        }

        // 7.必要时转换返回值
        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.

            // 恢复ThreadLocal中的旧代理对象
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

invoke()方法的处理流程大体如下:

  1. 获取到目标对象,也就是被代理对象的引用;
  2. 处理exposeProxy属性,如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中;
  3. 获得目标方法对应的拦截器链;
  4. 如果对应的拦截器链为空,也就是没有可以应用到此方法的通知(Interceptor),则直接通过反射方式进行调用;
  5. 如果拦截器链不为空,则需要创建一个MethodInvocation(方法调用对象),调用其proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法;
  6. 有需要的话,转换返回值;

invoke()方法内部有三个比较重要的方法:

  • getInterceptorsAndDynamicInterceptionAdvice():获得目标方法对应的拦截器链
// org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    // 1、首先从缓存中查找是否存在拦截器链
    //		private transient Map<MethodCacheKey, List<Object>> methodCache;  存放方法Method ==> 拦截器链集合的对应关系
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        // 2、如果缓存中不存在拦截器链,则委托getInterceptorsAndDynamicInterceptionAdvice()方法继续查找
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
        // 3、将前面一个步骤找到的拦截器链存入缓存中
        this.methodCache.put(cacheKey, cached);
    }
    // 4、如果缓存中存在拦截器链的话,则直接返回
    return cached;
}

首先从缓存中查找是否存在拦截器链,如果存在的话,直接获取到并返回;如果获取不到,则委托getInterceptorsAndDynamicInterceptionAdvice()方法继续查找,在本例子,因为第一次进来,缓存中肯定没有,所以走的是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.

    // 使用单例模式创建DefaultAdvisorAdapterRegistry实例
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    // 从config中获取所有的advisors增强器
    Advisor[] advisors = config.getAdvisors();

    // 保存拦截器集合,长度就是增强器的总数量
    List<Object> interceptorList = new ArrayList<>(advisors.length);

    // 目标类
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

    // 判断是否包含IntroductionAdvisor类型的增强器
    Boolean hasIntroductions = null;

    // 遍历advisors数组,根据不同类型的Advisor做不同的处理
    for (Advisor advisor : advisors) {
        // 如果advisor是PointcutAdvisor类型,判断advisor能否应用到目标方法
        if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                // 检查当前advisor的pointcut是否可以匹配当前方法
                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);
                }
                // 如果匹配的话,将增强器转换成MethodInterceptor拦截器对象
                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) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        // 如果advisor是IntroductionAdvisor类型,判断advisor能否应用到目标类
        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;
}

首先获取到所有的增强器,然后循环遍历,根据不同类型的Advisor做不同的处理。在本例中,增强器都是PointcutAdvisor类型,接着会MethodMatcher#match()方法检查当前advisor的pointcut是否可以匹配当前方法。如果匹配的话,则将增强器转换成MethodInterceptor拦截器对象。

具体逻辑在DefaultAdvisorAdapterRegistry#getInterceptors()方法:

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    // 如果是MethodInterceptor类型的通知,则直接加入集合中
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    
    // 通过适配器将advisor转换为MethodInterceptor拦截器
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(将advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}

执行完getInterceptorsAndDynamicInterceptionAdvice()方法后,已经将Advisor增强器转换为了MethodInterceptor对象,如下图:

接着,Spring会将获取到的MethodInterceptor对象存入缓存,以便下次可以从缓存中直接获取。

  • invokeJoinpointUsingReflection():通过反射方式调用目标方法

处理过程比较简单,就是通过method.invoke()反射调用目标方法的过程,源码如下:

// org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection
// 通过反射方式调用目标方法
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
    throws Throwable {

    // Use reflection to invoke the method.
    try {
        // 设置可访问权限
        ReflectionUtils.makeAccessible(method);
        // 使用反射调用目标方法
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {
        // Invoked method threw a checked exception.
        // We must rethrow it. The client won't see the interceptor.
        throw ex.getTargetException();
    }
    catch (IllegalArgumentException ex) {
        throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                                         method + "] on target [" + target + "]", ex);
    }
    catch (IllegalAccessException ex) {
        throw new AopInvocationException("Could not access method [" + method + "]", ex);
    }
}
  • MethodInvocation#proceed():执行拦截器链方法

在本例子中,目标方法对应的拦截器链不为空,所以需要根据代理对象、被代理对象、目标方法、目标方法的执行参数、拦截器链实例化一个MethodInvocation方法执行对象。

MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain)

接着调用MethodInvocation#proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法。这里就开始拦截器链的执行流程了,Spring使用了责任链模式实现。

// ReflectiveMethodInvocation.proceed()
// 开始执行拦截器链增强方法
public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.

    // 1.当前拦截器下标:从-1的位置开始, 直到满足索引下标 =(拦截器的长度  -1)的条件(所有拦截器都执行完毕),此时需要执行目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 执行目标方法
        return invokeJoinpoint();
    }

    // 2.每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器
    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;
        // 目标类所属类型
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());

        // 动态匹配,判断运行时参数是否匹配
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            // 如果匹配成功,则执行当前拦截器逻辑
            return dm.interceptor.invoke(this);
        } else {
            // 如果匹配失败,则会跳过当前拦截器interceptor,则会调用proceed()方法执行拦截器链中的下一个拦截器的处理
            return proceed();
        }

    } else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.

        // 3.只是一个普通的拦截器,则触发拦截器链责任链的调用,并且参数为ReflectiveMethodInvocation本身
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

proceed()方法的执行流程大体如下:

  1. 判断是否所有的拦截器已经执行完成,从-1(当前拦截器下标)的位置开始, 直到满足索引下标 =(拦截器的长度 -1)的条件(即所有拦截器都执行完毕),此时需要执行目标方法(在本例中就是执行addUser()方法);
  2. 每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器;
  3. 判断是否是InterceptorAndDynamicMethodMatcher动态方法匹配拦截器类型还是普通拦截器类型,分别做不同的处理;

我们继续跟踪代码:

这里我们的的拦截器总共有五个,如下图:

所以this.interceptorsAndDynamicMethodMatchers.size() - 1 = 4,每次进来proceed()方法都会执行如下判断:

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    // 执行目标方法
    return invokeJoinpoint();
}

(1)、proceed()方法第一次进来: 当前拦截器索引为-1,-1 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(0)获取到第一个拦截器:也就是默认的ExposeInvocationInterceptor拦截器,ExposeInvocationInterceptor只是一个普通的拦截器,则触发拦截器链责任链的调用,执行invoke()方法;

public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		// 将MethodInvocation对象存入ThreadLocal中
		invocation.set(mi);
		try {
			// 执行链中下一个拦截器的逻辑
			return mi.proceed();
		} finally {
			// 重置原来的MethodInvocation
			invocation.set(oldInvocation);
		}
	}

当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。

(二)、proceed()方法第二次进来: 当前拦截器索引为0,0 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(1)获取到第二个拦截器:也就是AfterReturningAdviceInterceptor拦截器,AfterReturningAdviceInterceptor也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AfterReturningAdviceInterceptor.invoke()方法:

// org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
    Object retVal = mi.proceed();
    // 这里没有try-catch,如果方法是异常退出的话,则不会调用@AfterReturning通知方法
    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    return retVal;
}

当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。

(三)、proceed()方法第三次进来: 当前拦截器索引为1,1 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(2)获取到第三个拦截器:也就是AspectJAfterAdvice拦截器,AspectJAfterAdvice也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AspectJAfterAdvice.invoke()方法:

// org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        // 调用下一个拦截器的逻辑
        return mi.proceed();
    } finally {
        // 不管方法正常退出还是异常退出,都会调用@After通知方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。

(四)、proceed()方法第四次进来: 当前拦截器索引为2,2 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(3)获取到第四个拦截器:也就是AspectJAroundAdvice拦截器,AspectJAroundAdvice也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AspectJAroundAdvice.invoke()方法:

// org.springframework.aop.aspectj.AspectJAroundAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
    if (!(mi instanceof ProxyMethodInvocation)) {
        throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
    }
    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    // 拿到pointcut切入点表达式
    JoinPointMatch jpm = getJoinPointMatch(pmi);
    // 执行通知方法进行增强
    return invokeAdviceMethod(pjp, jpm, null, null);
}
// org.springframework.aop.aspectj.AbstractAspectJAdvice#invokeAdviceMethod()
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
                                    @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
    // argBinding(): 获取方法执行连接点处的参数
    // invokeAdviceMethodWithGivenArgs(): 使用给定的参数调用增强方法
    return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
    Object[] actualArgs = args;
    // 如果通知方法不包含参数,则将actualArgs置为null
    if (this.aspectJAdviceMethod.getParameterCount() == 0) {
        actualArgs = null;
    }
    try {
        // 设置可访问权限
        ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);

        // 通过反射执行通知方法
        return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
    }
    catch (IllegalArgumentException ex) {
        throw new AopInvocationException("Mismatch on arguments to advice method [" +
                                         this.aspectJAdviceMethod + "]; pointcut expression [" +
                                         this.pointcut.getPointcutExpression() + "]", ex);
    }
    catch (InvocationTargetException ex) {
        throw ex.getTargetException();
    }
}

此时就会来到com.wsh.aop.SimpleAspect#around()环绕通知方法的执行:

// 环绕通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws InterruptedException {
    String methodName = proceedingJoinPoint.getSignature().getName();
    System.out.println("执行" + methodName + "的环绕通知(@Around)...");
    try {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println(methodName + "()方法耗时: " + (endTime - startTime) + "毫秒");
        return result;
    } catch (Throwable throwable) {
        throwable.printStackTrace();
        return null;
    }
}

当执行到proceedingJoinPoint.proceed()时,这时候又回到ReflectiveMethodInvocation#proceed()方法执行。

(五)、proceed()方法第五次进来: 当前拦截器索引为3,3 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(4)获取到第五个拦截器:也就是MethodBeforeAdviceInterceptor拦截器,MethodBeforeAdviceInterceptor也是一个普通的拦截器,则触发拦截器链责任链的调用,执行MethodBeforeAdviceInterceptor.invoke()方法:

// 
public Object invoke(MethodInvocation mi) throws Throwable {
    // 执行前置通知方法
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    // 调用下一个拦截器的逻辑
    return mi.proceed();
}

执行this.advice.before()方法时,就会来到com.wsh.aop.SimpleAspect#before(),执行前置通知的逻辑:

// 前置通知
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行" + methodName + "的前置通知(@Before)...");
}

前置通知执行完成后, 调用mi.proceed()会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。

(六)、proceed()方法第六次进来: 当前拦截器索引为4,4 = 4,所以会执行invokeJoinpoint()方法了。

// org.springframework.aop.framework.ReflectiveMethodInvocation#invokeJoinpoint
protected Object invokeJoinpoint() throws Throwable {
    // 通过反射执行目标方法
    // target:被代理的对象实例
    // method:执行的方法
    // arguments:方法参数
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

当执行 AopUtils.invokeJoinpointUsingReflection的时候,就会来到我们的目标方法的执行了:

public void addUser() {
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("新增用户...");
	}

当目标方法执行完成后,就会执行com.wsh.aop.SimpleAspect#around()后置通知:proceedingJoinPoint.proceed()后面的逻辑了。

Around环绕通知处理完成后, 就来到:AspectJAfterAdvice#invoke()方法处理@After通知方法了:

public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        // 调用下一个拦截器的逻辑
        return mi.proceed();
    } finally {
        // 不管方法正常退出还是异常退出,都会调用@After通知方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

可以看到,不管方法正常退出还是异常退出,都会调用@After通知方法。

invokeAdviceMethod()方法就会来到:com.wsh.aop.SimpleAspect#after

// 后置通知
@After("pointcut()")
public void after(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行" + methodName + "的后置通知(@After)...");
}

@After后置返回通知执行完成后,就会来到AfterReturningAdviceInterceptor#invoke()方法:

// org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
    Object retVal = mi.proceed();
    // 这里没有try-catch,如果方法是异常退出的话,则不会调用@AfterReturning通知方法
    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    return retVal;
}

// org.springframework.aop.aspectj.AspectJAfterReturningAdvice#afterReturning
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
    if (shouldInvokeOnReturnValueOf(method, returnValue)) {
        invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
    }
}

接着就执行com.wsh.aop.SimpleAspect#afterReturning返回通知的逻辑:

// 返回通知
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint) {
    String methodName = joinPoint.getSignature().getName();
    System.out.println("执行" + methodName + "的后置返回通知(@AfterReturning)...");
}

 至此,一次完整的AOP执行流程就算执行完了,我们对照前面的分析以及控制台的输出结果:

执行addUser的环绕通知(@Around)...
执行addUser的前置通知(@Before)...
新增用户...
addUser()方法耗时: 96730毫秒
执行addUser的后置通知(@After)...
执行addUser的后置返回通知(@AfterReturning)...

可以看到,输出的执行顺序与我们分析的顺序是一致的,Spring使用责任链模式依次处理拦截器链上所有的通知方法,前一个拦截器需要等后面的拦截器执行完成后才能执行。

三、总结

下面我们通过一张图说明拦截器链的整体执行流程:

至此,Spring AOP相关内容就介绍完毕了,从AOP相关术语、@EnableAspectJAutoProxy注解解析、增强器的获取、创建对象流程、AOP通知方法的执行流程等方面,详细总结了AOP知识。

最后,总结一下AOP的核心流程:

1)、通过@EnableAspectJAutoProxy注解开启AOP功能;

2)、解析@EnableAspectJAutoProxy注解,并注册AnnotationAwareAspectJAutoProxyCreator组件,AOP的准备和代理创建都在这个组件中完成;
3)、AnnotationAwareAspectJAutoProxyCreator继承AbstractAuto ProxyCreator实现了InstantiationAwareBeanPostProcessor接口,在方法postProcessBeforeInstantiation()中找到Spring容器中所有的增强器,为创建代理做准备;

4)、当我们的 bean 初始化完毕后,会触发所有 BeanPostProcessor 的 postProcessAfterInitialization()方法,AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator实现了BeanPostProcessor接口,此时就会调用我们的 AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization()方法,在方法postProcessAfterInitialization()中通过前面找到的候选增强器中找到合适的增强器来创建代理对象;

5)、当调用到被 AOP 代理的方法时,会走到对应的代理方法:JdkDynamicAopProxy#invoke 或 DynamicAdvisedInterceptor#intercept,该方法会创建 ReflectiveMethodInvocation,通过责任链的方式来执行所有的增强器和被代理的方法;

举报

相关推荐

0 条评论