【源码剖析】Spring AOP 详解

shadowLogo

在之前的博文中,本人讲解了 Spring IOC 的相关源码
并在大概一年前的博文中,也自己半实现了 AOP 的功能
但是,作为一个学生党,自己实现的肯定和 Spring AOP 大相径庭

那么,在本篇博文中,本人就来讲解下 Spring AOP 的相关源码:


首先,本人来给出一个调用了 Spring AOP 所提供的 API 的Demo:

API调用:

切面类:

package edu.youzg.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspect {

    @Pointcut("execution(* edu.youzg.aop..*.*(..))")
    public void anyMethod() {
    }

    //前置通知:在目标方法执行前执行-->目标方法的第一行
    @Before("anyMethod()")
    public void before(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        String mname = joinPoint.getSignature().getName();
        String cname = joinPoint.getTarget().getClass().getName();
        //输出什么类,什么方法,什么时间,什么参数被执行了
        String msg = String.format("before====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
        System.out.println(msg);
    }


    // <!--最终通知-->
    @AfterReturning("anyMethod()")
    public void returning(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        String mname = joinPoint.getSignature().getName();
        String cname = joinPoint.getTarget().getClass().getName();
        //输出什么类,什么方法,什么时间,什么参数被执行了
        String msg = String.format("AfterReturning====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
        System.out.println(msg);
    }


    // <!--后置通知-->
    @After("anyMethod()")
    public void after(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        String mname = joinPoint.getSignature().getName();
        String cname = joinPoint.getTarget().getClass().getName();
        //输出什么类,什么方法,什么时间,什么参数被执行了
        String msg = String.format("after====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
        System.out.println(msg);
    }

    //<!--异常通知-->
    @AfterThrowing(value = "anyMethod()", throwing = "t")
    public void throwing(JoinPoint joinPoint, Throwable t) {
        System.out.println("=========AfterThrowing===========" + t.getMessage());
    }

    // <!--环绕通知-->
    @Around("anyMethod()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        System.out.println("======around方法开始执行之前");
        result = pjp.proceed();
        System.out.println("=======around方法开始执行完毕");
        return result;
    }

}

业务类:

package edu.youzg.aop.service;

import org.springframework.stereotype.Service;

/**
 * @Author: Youzg
 * @CreateTime: 2020-05-01 20:33
 * @Description:带你深究Java的本质!
 */
@Service
public class UserServiceImpl {

    public void login() {
        System.out.println("service层login方法执行!");
    }



    public void register() {
        System.out.println("service层register方法执行!");
    }

    public void rename() {
        System.out.println("service层rename方法执行!");
    }

    public void cancellat() {
        System.out.println("service层cancellat方法执行!");
    }

}

配置类:

package edu.youzg.aop.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
@ComponentScan("edu.youzg.aop")
public class YouzgConfig {
}

测试类:

package edu.youzg.aop.demo;

/**
 * @Author: Youzg
 * @CreateTime: 2021-03-20 16:50
 * @Description: 带你深究Java的本质!
 */

import edu.youzg.aop.config.YouzgConfig;
import edu.youzg.aop.service.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author: Youzg
 * @CreateTime: 2020-05-01 20:40
 * @Description:带你深究Java的本质!
 */
public class YouzgTest {


    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(YouzgConfig.class);
        UserServiceImpl userService = context.getBean("userServiceImpl", UserServiceImpl.class);
        userService.login();
    }

}

那么,本人现在来展示下 运行结果
运行结果


结合源码 进行讲解之前,本人先来 简要总结Spring AOP执行流程

执行流程:

其实,只要我们仔细思考,都能想到:

  1. 筛选 Advisors
  2. 创建 代理对象
  3. 执行 代理对象 的 增强方法

现在,本人就来通过源码,来讲解下 Spring AOP 是如何 实现上述步骤的:

AOP代理构建入口:

在之前的博文《【源码剖析】Spring IOC 详解》中,本人也讲过:

Spring AOP部分实现逻辑,在 AbstractAutoProxyCreator类postProcessAfterInitialization()方法 中实现
因为 AOP 只有在 初始化了目标bean对象 后,才能 创建 动态代理

那么,本人再来展示下那部分源码:
相关源码
那么,本人来展示下 为 bean对象,创建代理对象 的相关代码:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }

    /*
     * 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类,
     * 则不应该生成代理,此时直接返回 bean
     */ 
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        // 将 <cacheKey, FALSE> 键值对放入缓存中,供上面的 if 分支使用
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 为目标 bean 查找合适的通知器
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    /*
     * 若 specificInterceptors != null,即 specificInterceptors != DO_NOT_PROXY,
     * 则为 bean 生成代理对象,否则直接返回 bean
     */ 
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        /*
         * 返回代理对象,此时 IOC 容器输入 bean,得到 proxy。此时,
         * beanName 对应的 bean 是代理对象,而非原始的 bean
         */ 
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    // specificInterceptors = null,直接返回 bean
    return bean;
}

构建 Advisors列表:

我们跟进去 第20行代码,看看是如何执行的:
查找通知器
可以看到:

这个方法的 作用 是:
获取 匹配上的通知器

那么,我们来跟进去,看看究竟是如何 获取到匹配的通知器 的:
向下执行
我们跟进 上图中的76行,来看下时如何查询的:
76
继续跟进 94行 代码:
94
可以看到,使用一个 Helper 进行了封装
(我们可以理解 XxxHelper操作Xxx的工具)

那么,我们继续向下跟:

筛选Advisors:

public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = null;
    synchronized (this) {
        // cachedAdvisorBeanNames 是 advisor 名称的缓存
        advisorNames = this.cachedAdvisorBeanNames;
        /*
         * 如果 cachedAdvisorBeanNames 为空,这里到容器中查找,
         * 并设置缓存,后续直接使用缓存即可
         */ 
        if (advisorNames == null) {
            // 从容器中查找 Advisor 类型 bean 的名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            // 设置缓存
            this.cachedAdvisorBeanNames = advisorNames;
        }
    }
    if (advisorNames.length == 0) {
        return new LinkedList<Advisor>();
    }

    List<Advisor> advisors = new LinkedList<Advisor>();
    // 遍历 advisorNames
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            // 忽略正在创建中的 advisor bean
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    /*
                     * 调用 getBean 方法从容器中获取名称为 name 的 bean,
                     * 并将 bean 添加到 advisors 中
                     */ 
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                            if (logger.isDebugEnabled()) {
                                logger.debug("Skipping advisor '" + name +
                                        "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }

    return advisors;
}

本人来总结下 上面源码作用

  • 在容器中,查找所有 类型为AdvisorbeanName
  • 遍历 advisorNames,并从容器中获取 对应的 bean实例对象

我们继续向下跟进:
跟进

继续跟进:
判断切面类型
可以看到:

在上面的方法中,检验了每一个Advisor的 合法性

那么,我们再来看看后面的 sortAdvisors()方法

排序各个Advisors:

排序
我们再来跟进下 153行 代码:
跟进
我们来看看 INSTANCE 这个 排序器排序规则
继承关系
可以看到:

使用了 自定义排序器 进行了 排序

而具体是按照什么顺序呢?
顺序
具体是怎么读取的,本人就不在这里展示了
同学们只要知道上述的实现步骤就可以了

那么,排序之后,整个 有序的Advisor列表 就会被返回


之后,就会执行 添加扩展Advisor 的操作:

添加扩展Advisor:

添加扩展
我们点进去:

public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // 如果通知器列表是一个空列表,则啥都不做
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        /*
         * 下面的 for 循环用于检测 advisors 列表中是否存在 
         * AspectJ 类型的 Advisor 或 Advice
         */
        for (Advisor advisor : advisors) {
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
            }
        }

        /*
         * 向 advisors 列表的首部添加 DefaultPointcutAdvisor,
         * 便于之后的操作
         */
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}

private static boolean isAspectJAdvice(Advisor advisor) {
    return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
            advisor.getAdvice() instanceof AbstractAspectJAdvice ||
            (advisor instanceof PointcutAdvisor &&
                     ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}

这里的代码,作用也很简单:

Advisor列表首部 添加 DefaultPointcutAdvisor通知器

那么,上述通知器究竟有什么作用,本人将在下文进行阐述!


那么,接下来就是 创建代理对象 的操作:

创建 代理对象:

我们继续向下执行,到 AOP代理构建入口 方法第35行 时,就会创建 目标bean对象代理对象
创建代理对象
那么,我们跟进去看看是如何创建的:

参数检验,构建Advisors:

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    /*
     * 默认配置下,或用户显式配置 proxy-target-class = "false" 时,
     * 这里的 proxyFactory.isProxyTargetClass() 也为 false
     */
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            /*
             * 检测 beanClass 是否实现了接口,若未实现,则将 
             * proxyFactory 的成员变量 proxyTargetClass 设为 true
             */ 
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // specificInterceptors 中若包含有 Advice,此处将 Advice 转为 Advisor
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 创建代理
    return proxyFactory.getProxy(getProxyClassLoader());
}

我们继续跟进 上面代码中 的 最后一行代码

创建代理对象:

包装

我们来看看是如何创建 AOP代理对象 的:

AOP代理对象 的构建:

我们继续向下跟进:
继续跟进
DefaultAopProxyFactory类:

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    /*
     *   条件1:config.isOptimize() - 是否需要优化
     *   条件2:config.isProxyTargetClass() - 检测 proxyTargetClass 的值
     *   条件3:hasNoUserSuppliedProxyInterfaces(config) 
     *         - 目标 bean 是否实现了接口
     */
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 创建 CGLIB 代理,ObjenesisCglibAopProxy 继承自 CglibAopProxy
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        // 创建 JDK 动态代理
        return new JdkDynamicAopProxy(config);
    }
}

可以看到:

这个方法的作用是:
根据之前的扫描结果 和 被代理的bean
选择 创建 Cglib代理 或是 JDK动态代理


那么,最后,我们来看看 创建代理对象getProxy()方法 是怎样执行的:

创建 bean的代理对象:

代理对象
我们来看看其实现类:
创建代理
那么,我们再来看看这两个实现类会怎么执行:
cglib
jdk代理
可以看到:

在上面的方法中,调用了 cglib代理方法jdk动态代理方法原生API,创建了 bean的代理对象
但是,在创建之后,并没有返回 原生的代理对象
而是进行了一层封装,返回了 AOP封装的代理对象,这就决定了,之后的 代理对象执行方法,也要按照 AOP的顺序 来执行

如下图
代理


那么,本人来通过一张 流程图总结创建代理对象流程

代理对象 创建流程:

执行流程


在这里,本人先说明一点:

cglib代理,对于每一个被代理的方法,都会创建 派生类
在我们执行方法时,内部会根据一定的 路由规则,向每一个派生类 派发 任务,由它们去执行

那么,在本篇博文中,本人就以JDK动态代理的 执行流程,来讲解下 Spring AOP执行增强方法流程

执行 增强方法:

首先,是 方法执行的入口

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 {
        // 省略部分代码
        Object retVal;

        // 如果 expose-proxy 属性为 true,则暴露代理对象
        if (this.advised.exposeProxy) {
            // 向 AopContext 中设置代理对象
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // 获取 拦截器链(与当前方法匹配的拦截器和通知器)
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // 如果 拦截器链 为空,则 直接执行目标方法
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            // 通过反射执行目标方法
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // 创建一个方法调用器,并将拦截器链传入其中
            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())) {
            // 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal 
            retVal = proxy;
        }
        // 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常
        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()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

经过阅读上面的源码,本人来做一下总结:

  • 判断是否 暴露代理对象
  • 获取 拦截器链(与当前方法匹配的拦截器和通知器)
  • 拦截器链为空,则 直接通过反射执行目标方法
    拦截器链不为空,则 创建方法调用 ReflectiveMethodInvocation 对象
  • 调用 ReflectiveMethodInvocation 对象的 proceed() 方法 ,调用 整条拦截器链
  • 处理返回值,并返回该值

那么,我们先来看看 是如何 获取拦截器链 的:

获取 拦截器链:

向下调用获取
我们继续跟下去:

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

    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    // registry 为 DefaultAdvisorAdapterRegistry 类型
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    // 遍历 advisor列表
    for (Advisor advisor : config.getAdvisors()) {
        if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            /*
             * 调用 ClassFilter 对 bean 类型进行匹配,无法匹配则说明当前通知器
             * 不适合应用在当前 bean 上
             */
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                // 将 advisor 中的 advice 转成相应的拦截器
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                // 通过方法匹配器对目标方法进行匹配
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                    // 若 isRuntime 返回 true,则表明 MethodMatcher 要在运行时做一些检测
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            // IntroductionAdvisor 类型的通知器,仅需进行类级别的匹配即可
            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 经过筛选校验,并 转换成相应的 interceptor

因为在 原生API调用过程中,是没有 通知器 的概念的
通知器是Spring抽象概念化出来的,其本质依然是 拦截器

就像 Spring MVC 中的每一个 mapping,其本质都是 Servlet
(相关核心源码,本人将在之后的博文中进行讲解)


那么,现在我们来看看,Spring AOP 是如何 将每一个 advisor 转换成 interceptor 的:

advisor -> interceptor:

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
    Advice advice = advisor.getAdvice();
    /*
     * 若 advice 是 MethodInterceptor 类型的,直接添加到 interceptors 中即可
     * (AspectJAfterAdvice 就实现了 MethodInterceptor 接口)
     */
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }

    /*
     * 对于 AspectJMethodBeforeAdvice 等类型的通知,由于没有实现 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[interceptors.size()]);
}

那么,适配器是如何将 **advisor ** 转换成 interceptor 的呢?

我们继续跟下去:
包装
我们能看到:

只是调用了 拦截器的单参构造

那么,到这里,本人就不跟下去了


我们来看看之后要执行的代码:

调用 拦截器链:

private int currentInterceptorIndex = -1;

public Object proceed() throws Throwable {
    // 执行到最后一个拦截器,就执行 目标方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 执行 目标方法
        return invokeJoinpoint();
    }

    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        /*
         * 调用具有三个参数(3-args)的 matches 方法动态匹配目标方法,
         * 两个参数(2-args)的 matches 方法用于 静态匹配
         */
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
            // 调用拦截器逻辑
            return dm.interceptor.invoke(this);
        }
        else {
            // 如果匹配失败,则忽略当前的拦截器
            return proceed();
        }
    }
    else {
        // 执行 拦截器方法
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

上面的代码,看似很长,其实我们自己看,本质上只是在 调用 拦截器链中的拦截器方法


在上面的代码中,我们能够看到,有一个方法被执行了很多次 —— invoke()方法

拦截器 的 invoke:

在上面的代码中,我们也能发现:

每一个advisor,根据其类型不同,所构建的拦截器也是不同的

那么,本人来展示下每一个拦截器的 invoke()方法 的具体实现流程:

ExposeInvocationInterceptor

invokeE
我们可以看得出来,这里的 执行逻辑 为:

  • 更新 ThreadLocal 的 invocation
  • 继续 执行 下一个拦截器 的逻辑

AspectJAfterThrowingAdvice:

invokeA
我们可以看得出来,这里的 执行逻辑 为:

  • 继续 执行 下一个拦截器 的逻辑
  • 出现异常,再执行 当前拦截器异常处理逻辑

AfterReturningAdviceInterceptor:

invokeAR
我们可以看得出来,这里的 执行逻辑 为:

  • 继续 执行 下一个拦截器 的逻辑
  • 执行完毕后,执行 当前拦截器 的逻辑

AspectJAfterAdvice:

invokeAA
我们可以看得出来,这里的 执行逻辑 为:

  • 继续 执行 下一个拦截器 的逻辑
  • 执行完毕后,再执行 当前拦截器 的逻辑

MethodBeforeAdviceInterceptor:

invokeMB
我们可以看得出来,这里的 执行逻辑 为:

  • 执行 当前拦截器 的逻辑
  • 继续 执行 下一个拦截器的逻辑

那么,我们再来看看 目标方法执行逻辑

invokeJoinpoint()方法:

包装
包装方法,我们继续向下跟进:
反射
由此,我们可以看出:

当执行到 原方法(拦截器链中的最后一个方法):
执行完后,就会通过 递归调用栈,一层一层向上面的方法中,执行 之后的逻辑


那么,由上面的源码,我们也能看出,这是一种 职责链的设计模式

执行顺序:

再经过上文中,本人讲解的拦截器链的排序规则,我们可以理解 当前拦截器链执行顺序 为:
执行顺序


参考文章:

《Spring AOP 源码分析》


那么,到这里,Spring AOP 的核心源码就讲解完毕了!

在之后的博文中,本人也将讲解下 Spring 事务 的 相关源码
再讲解些比较常考的面试题,Spring Framework 系列源码,就结束了!
觉得有帮助的同学,请不吝赞赞和关注哦表情ヾ(≧▽≦*)o

posted @ 2021-03-21 13:41  在下右转,有何贵干  阅读(179)  评论(0编辑  收藏  举报