死磕Spring之AOP篇 - Spring AOP自动代理(二)筛选合适的通知器
阅读原文时间:2021年04月21日阅读:1

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读。

Spring 版本:5.1.14.RELEASE

在开始阅读 Spring AOP 源码之前,需要对 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章导读》 这一系列文章

了解 AOP 相关术语,可先查看 《Spring AOP 常见面试题) 》 这篇文章

该系列其他文章请查看:《死磕 Spring 之 AOP 篇 - 文章导读》

在上一篇《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:

  1. 筛选出能够应用于当前 Bean 的 Advisor
  2. 找到了合适 Advisor 则创建一个代理对象, JDK 动态代理或者 CGLIB 动态代理

本文就接着上篇文章来分析筛选合适的通知器的处理过程,包含 @AspectJAspectJ 注解的解析过程。这里的“通知器”指的是 Advisor 对象。

回顾

// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    /*
     * <1> 如果当前 Bean 已经创建过自定义 TargetSource 对象
     * 表示在上面的**实例化前置处理**中已经创建代理对象,那么直接返回这个对象
     */
    if (StringUtils.hasLength(beanName)
            && this.targetSourcedBeans.contains(beanName))
    {
        return bean;
    }
    // <2> `advisedBeans` 保存了这个 Bean 没有必要创建代理对象,则直接返回
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    /*
     * <3> 不需要创建代理对象,则直接返回当前 Bean
     */
    if (isInfrastructureClass(bean.getClass()) // 如果是 Spring 内部的 Bean(Advice、Pointcut、Advisor 或者 AopInfrastructureBean 标记接口)
            || shouldSkip(bean.getClass(), beanName)) // 应该跳过
    {
        // 将这个 Bean 不需要创建代理对象的结果保存起来
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // <4> 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // <5> 如果有 Advisor,则进行下面的动态代理创建过程
    if (specificInterceptors != DO_NOT_PROXY) {
        // <5.1> 将这个 Bean 已创建代理对象的结果保存至 `advisedBeans`
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // <5.2> 创建代理对象,JDK 动态代理或者 CGLIB 动态代理
        // 这里传入的是 SingletonTargetSource 对象,可获取代理对象的目标对象(当前 Bean)
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // <5.3> 将代理对象的 Class 对象(目标类的子类)保存
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // <5.4> 返回代理对象
        return proxy;
    }

    // <6> 否则,将这个 Bean 不需要创建代理对象的结果保存起来
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    // <7> 返回这个 Bean 对象
    return bean;
}

在创建代理对象的过程中,上面方法的第 4 步调用 getAdvicesAndAdvisorsForBean(..) 方法,获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)

// AbstractAutoProxyCreator.java
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
            @Nullable TargetSource customTargetSource) throws BeansException;

抽象方法,交由子类实现

筛选出合适的 Advisor 的流程

  1. 解析出当前 IoC 容器所有 Advisor 对象

  2. 筛选出能够应用于这个 Bean 的 Advisor 们,主要通过 ClassFilter 类过滤器和 MethodMatcher 方法匹配器进行匹配

  3. 对筛选出来的 Advisor 进行扩展,例如子类会往首部添加一个 PointcutAdvisor 对象

  4. 对筛选出来的 Advisor 进行排序

    • 不同的 AspectJ 根据 @Order 排序

    • 同一个 AspectJ 中不同 Advisor 的排序,优先级:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice

主要涉及到下面几个类:

  • AbstractAdvisorAutoProxyCreator:支持从当前 Spring 上下文获取所有 Advisor 对象
  • AnnotationAwareAspectJAutoProxyCreator:支持从带有 @AspectJ 注解 Bean 中解析 Advisor 对象
  • BeanFactoryAspectJAdvisorsBuilder:Advisor 构建器,用于解析出当前 BeanFactory 中所有带有 @AspectJ 注解的 Bean 中的 Advisor
  • ReflectiveAspectJAdvisorFactory:Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor

AnnotationAwareAspectJAutoProxyCreator 继承 AbstractAdvisorAutoProxyCreator,借助 BeanFactoryAspectJAdvisorsBuilder 构建器,这个构建器又借助 ReflectiveAspectJAdvisorFactory 工厂。

AbstractAdvisorAutoProxyCreator

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator:支持从当前 Spring 上下文获取所有 Advisor 对象,存在能应用与 Bean 的 Advisor 则创建代理对象

构造函数

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    /** Advisor 检索工具类 */
    @Nullable
    private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        // 初始化工作
        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }

    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 设置 Advisor 检索工具类为 BeanFactoryAdvisorRetrievalHelperAdapter
        this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
    }
}

1. getAdvicesAndAdvisorsForBean 方法

getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource),筛选某个 Bean 合适的 Advisor,如下:

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
        Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    // 转换成数组并返回
    return advisors.toArray();
}

调用 findEligibleAdvisors(Class<?> beanClass, String beanName) 方法,获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)

2. findEligibleAdvisors 方法

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    /*
     * <1> 解析出当前 IoC 容器所有的 Advisor 对象
     * 1. 本身是 Advisor 类型的 Bean,默认情况下都会
     * 2. 从带有 @AspectJ 注解的 Bean 中解析出来的 Advisor,子类 AnnotationAwareAspectJAutoProxyCreator 会扫描并解析
     *    PointcutAdvisor:带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法
     *       其中 Pointcut 为 AspectJExpressionPointcut,Advice 就是注解标注的方法
     *    IntroductionAdvisor:带有 @DeclareParents 注解的字段
     *
     * 未排序,获取到的 Advisor 在同一个 AspectJ 中的顺序是根据注解来的,@Around > @Before > @After > @AfterReturning > @AfterThrowing
     */
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    /*
     * <2> 筛选出能够应用到 `beanClass` 上面的所有 Advisor 对象并返回
     * 也就是通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
     * AspectJExpressionPointcut 就实现了 ClassFilter 和 MethodMatcher
     */
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    /*
     * <3> 抽象方法,交由子类拓展
     * 例如 AspectJAwareAdvisorAutoProxyCreator 的实现
     * 如果 `eligibleAdvisors` 中存在和 AspectJ 相关的 Advisor
     * 则会在 `eligibleAdvisors` 首部添加一个 DefaultPointcutAdvisor 对象,对应的 Advice 为 ExposeInvocationInterceptor 对象
     * 用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用
     */
    extendAdvisors(eligibleAdvisors);
    // <4> 对 `eligibleAdvisors` 集合进行排序,根据 @Order 注解进行排序
    if (!eligibleAdvisors.isEmpty()) {
        // 不同的 AspectJ 根据 @Order 排序
        // 同一个 AspectJ 中不同 Advisor 的排序:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    // <5> 返回排序后的能够应用到当前 Bean 的所有 Advisor
    return eligibleAdvisors;
}

该方法的处理过程如下:

  1. 调用 findCandidateAdvisors() 方法,解析出当前 IoC 容器所有的 Advisor 对象,得到 candidateAdvisors 集合,来源:

    • 本身是 Advisor 类型的 Bean,默认情况下都会
    • 从带有 @AspectJ 注解的 Bean 中解析出来的 Advisor
  2. 调用 findAdvisorsThatCanApply(..) 方法,筛选出能够应用到 beanClass 上面的所有 Advisor 对象并返回,得到 eligibleAdvisors 集合

    • 通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
  3. 调用 extendAdvisors(List<Advisor> candidateAdvisors) 方法,对 eligibleAdvisors 进行处理

  4. 调用 sortAdvisors(List<Advisor> advisors) 方法,对 eligibleAdvisors 进行排序

  5. 返回排序后的能够应用到当前 Bean 的所有 Advisor

接下来依次对上面的方法进行分析

2.1.1 findCandidateAdvisors 方法

findCandidateAdvisors(),该方法会去找符合条件的 Advisor 们,AbstractAdvisorAutoProxyCreator 的实现则是去找当前 IoC 容器中所有 Advisor 类型的 Bean,如下:

// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    // 借助 BeanFactoryAdvisorRetrievalHelperAdapter 从 IoC 容器中查找所有的 Advisor 对象
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

可以看到是借助于 BeanFactoryAdvisorRetrievalHelperAdapter 去找 Advisor 类型的 Bean,如下:

// BeanFactoryAdvisorRetrievalHelperAdapter.java
public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    // <1> 先从缓存中获取所有 Advisor
    String[] advisorNames = this.cachedAdvisorBeanNames;
    // <2> 没有缓存
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        // <2.1> 从当前 BeanFactory 容器中找到所有 Advisor 类型的 bean 的名称
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
        // <2.2> 放入缓存中
        this.cachedAdvisorBeanNames = advisorNames;
    }
    // <3> 如果没有 Advisor,则返回一个空集合
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    /*
     * <4> 遍历所有的 Advisor 类型的 Bean 的名称,获取对应的 Bean
     */
    for (String name : advisorNames) {
        // <4.1> 判断这个 Bean 是否有资格,默认为 true
        if (isEligibleBean(name)) {
            // <4.2> 正在初始化,则先跳过
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            }
            // <4.3> 否则,获取对应的 Bean
            else {
                try {
                    // 依赖查找到这个 Advisor 对象
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    // ...
                    throw ex;
                }
            }
        }
    }
    // <5> 返回 IoC 容器中所有的 Advisor
    return advisors;
}

该方法的处理过程如下:

  1. 先从缓存中获取所有 Advisor

  2. 没有缓存

  3. 如果没有 Advisor,则返回一个空集合

  4. 遍历所有的 Advisor 类型的 Bean 的名称,获取对应的 Bean

  5. 返回 IoC 容器中所有的 Advisor

总结下来,就是从当前 Spring IoC 容器中找到所有 Advisor 类型的 Bean

2.2 findAdvisorsThatCanApply 方法

findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) 方法,从 candidateAdvisors 中找到能够应用于 beanClass 的 Advisor,如下:

protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        /*
         * 筛选出能够应用到 `beanClass` 上面的所有 Advisor 对象并返回
         * 也就是通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
         * AspectJExpressionPointcut 就实现了 ClassFilter 和 MethodMatcher
         */
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

可以看到是借助于 AopUtils 工具类从 candidateAdvisors 中找到能够应用于 beanClass 的 Advisor,如下:

// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    /*
     * <1> 遍历所有的 Advisor 对象
     * 找到能够应用当前 Bean 的 IntroductionAdvisor 对象,放入 `eligibleAdvisors` 集合中
     */
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor // 如果是 IntroductionAdvisor 类型
                && canApply(candidate, clazz)) // 且能够应用到当前 Bean 中,通过其 ClassFilter 进行过滤
        {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    /*
     * <2> 遍历所有的 Advisor 对象
     * 如果是 IntroductionAdvisor 类型,则会跳过,因为上面已经判断过
     * 找到能够应用当前 Bean 的 Advisor 对象,放入 `eligibleAdvisors` 集合中
     */
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        // 判断是否能够应用到这个 Bean 上面
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    // <3> 返回能够应用到当前 Bean 的所有 Advisor 对象
    return eligibleAdvisors;
}

该方法的处理过程如下:

  1. 遍历所有的 Advisor 对象,找到能够应用当前 Bean 的 IntroductionAdvisor 对象,放入 eligibleAdvisors 集合中,需要满足下面两个条件

    • IntroductionAdvisor 类型
    • 能够应用到当前 Bean 中,通过其 ClassFilter 进行过滤
  2. 遍历所有的 Advisor 对象,找到能够应用当前 Bean 的 Advisor 对象,放入 eligibleAdvisors 集合中;如果是 IntroductionAdvisor 类型,则会跳过,因为上面已经判断过

  3. 返回能够应用到当前 Bean 的所有 Advisor 对象

AopUtils#canApply 方法

如何判断这个 Advisor 能够应用于某个 Bean 都是调用 canApply(..) 方法如下:

// AopUtils.java
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        /*
         * 从 IntroductionAdvisor 中获取 ClassFilter 类过滤器,判断这个目标类是否符合条件
         */
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
        /*
         * 根据 Pointcut 中的 ClassFilter 和 MethodFilter 进行过滤
         * 例如 Aspect 的实现类 AspectJExpressionPointcut
         */
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        // It doesn't have a pointcut so we assume it applies.
        // 否则,没有 Pointcut,也就是没有筛选条件,则都符合条件
        return true;
    }
}

如果 IntroductionAdvisor 类型的 Advisor 则通过 ClassFilter 类过滤器进行判断即可;如果是 PointcutAdvisor 类型的 Advisor 则需要调用 canApply(..) 的重载方法进行判断;否则,没有 Pointcut,也就是没有筛选条件,则都符合条件

AopUtils#canApply 重载方法

如何判断 PointcutAdvisor 类型的 Advisor 能够应用于某个 Bean 的过程如下:

// AopUtils.java
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    Assert.notNull(pc, "Pointcut must not be null");
    // <1> 使用 ClassFilter 匹配 `targetClass`
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }

    // <2> 获取 MethodMatcher 方法匹配器
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    // <3> 如果方法匹配器为 TrueMethodMatcher,则默认都通过
    if (methodMatcher == MethodMatcher.TRUE) {
        // No need to iterate the methods if we're matching any method anyway...
        return true;
    }

    // <4> 如果方法匹配器为 IntroductionAwareMethodMatcher,则进行转换
    // AspectJExpressionPointcut 就是 IntroductionAwareMethodMatcher 的实现类
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    /*
     * <5> 获取目标类、以及实现的所有接口,并添加至 `classes` 集合中
     */
    Set<Class<?>> classes = new LinkedHashSet<>();
    // <5.1> 如果不是 java.lang.reflect.Proxy 的子类
    if (!Proxy.isProxyClass(targetClass)) {
        // 获取目标类的 Class 对象(如果目标类是 CGLIB 代理对象,则获取其父类的 Class 对象,也就得到了目标类)
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    // <5.2> 获取目标类实现的所有接口,如果目标类本身是一个接口,那么就取这个目标类
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

    /*
     * <6> 遍历上面的 `classes` 集合
     */
    for (Class<?> clazz : classes) {
        // <6.1> 获取这个 Class 对象的所有方法
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        // <6.2> 遍历上一步获取到的所有方法
        for (Method method : methods) {
            // <6.3> 使用方法匹配器对该方法进行匹配,如果匹配成功则直接返回 `true`
            // AspectJExpressionPointcut 底层就是通过 AspectJ 进行处理的
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    // <7> 一个方法都没匹配则返回 `false`,表示这个 Advisor 不能应用到这个 Bean 上面
    return false;
}

该方法的处理过程如下:

  1. 使用 Pointcut 的 ClassFilter 匹配 targetClass,不通过则直接返回 false

  2. 获取 Pointcut 的 MethodMatcher 方法匹配器,保存至 methodMatcher

  3. 如果 methodMatcher 为 TrueMethodMatcher,则默认都通过,返回 true

  4. 如果 methodMatcher 为 IntroductionAwareMethodMatcher,则进行转换,保存至 introductionAwareMethodMatcher

    • AspectJExpressionPointcut 就是 IntroductionAwareMethodMatcher 的实现类
  5. 获取目标类、以及实现的所有接口,并添加至 classes 集合中

  6. 遍历上面的 classes 集合

  7. 一个方法都没匹配成功则返回 false,表示这个 Advisor 不能应用到这个 Bean 上面

总结下来,PointcutAdvisor 是根据 Pointcut 的 ClassFilter 对目标类进行过滤,如果通过的话,则通过 MethodMatcher 方法匹配器对目标类的方法进行匹配,有一个方法满足条件就表示这个 PointcutAdvisor 可以应用于目标类

2.3 extendAdvisors 方法

extendAdvisors(List<Advisor> candidateAdvisors) 放,对筛选出来的 Advisor 进行扩展,抽象方法,我们来看到子类的实现:

// AspectJAwareAdvisorAutoProxyCreator.java
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

可以看到是借助于 AspectJProxyUtils 工具类进行扩展,如下:

public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // Don't add advisors to an empty list; may indicate that proxying is just not required
    if (!advisors.isEmpty()) {
        boolean foundAspectJAdvice = false;
        // 遍历所有 Advisor
        for (Advisor advisor : advisors) {
            // Be careful not to get the Advice without a guard, as this might eagerly
            // instantiate a non-singleton AspectJ aspect...
            // 判断这个 Advisor 是否和 AspectJ 相关
            if (isAspectJAdvice(advisor)) {
                foundAspectJAdvice = true;
                break;
            }
        }
        // 如果 `advisors` 涉及到和 AspectJ 相关的 Advisor
        // 则向其首部添加一个 DefaultPointcutAdvisor 对象,对应的 Advice 为 ExposeInvocationInterceptor 对象
        // 用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用
        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) );
}

处理过程很简单,当存在和 AspectJ 相关的 Advisor(使用了 AspectJ 的注解这里都是 true),则在首部添加一个 DefaultPointcutAdvisor 对象

添加的这个 Advisor 对应的 Advice 为 ExposeInvocationInterceptor 方法拦截器,用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用

2.4 sortAdvisors 方法

sortAdvisors(List<Advisor> advisors) 方法,对筛选出来的 Advisor 进行排序,如下:

// AspectJAwareAdvisorAutoProxyCreator.java
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
    for (Advisor element : advisors) {
        // 使用 AspectJPrecedenceComparator 比较器
        partiallyComparableAdvisors.add(
                new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
    }
    List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
    if (sorted != null) {
        List<Advisor> result = new ArrayList<>(advisors.size());
        for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
            result.add(pcAdvisor.getAdvisor());
        }
        return result;
    }
    else {
        // AbstractAdvisorAutoProxyCreator
        // 使用 AnnotationAwareOrderComparator 比较器,通过 @Order 注解
        return super.sortAdvisors(advisors);
    }
}

AspectJPrecedenceComparator 是对 AnnotationAwareOrderComparator 的包装,进行了扩展,排序不同类型的 Advice,详细的过程这里不展述了

我通过 Debug 打断点得到的结论:

  • 不同的 AspectJ 根据 @Order 排序

  • 同一个 AspectJ 中不同 Advisor 的排序,优先级如下:

    AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice

小结

到这里我们可以一个结论,筛选合适的通知器的总的过程在 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(..) 方法中进行,分为下面几步:

  1. 找符合条件的 Advisor 们,在 AbstractAdvisorAutoProxyCreator 则是去找当前 IoC 容器中所有 Advisor 类型的 Bean
  2. 从上一步找到的 Advisor 筛选出能够应用于当前 Bean 的 Advisor 们,主要是通过 Pointcut 的 ClassFilter 类过滤器和 MethodMatcher 方法匹配器进行判断,有一个方法匹配这个 Advisor 即满足条件
  3. 支持对找到的 Advisor 集合进行扩展,在子类中会往其首部添加一个方法拦截器为 ExposeInvocationInterceptor 的 PointcutAdvisor
  4. 对找到的合适的 Advisor 进行排序,排序结果如上所述

上面过程的第 1 步仅找到当前 IoC 容器中所有 Advisor 类型的 Bean,是不是没有对 AspectJ 相关注解进行解析,这个过程在子类中实现,也就是接下来要讲的内容

AnnotationAwareAspectJAutoProxyCreator

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator:支持从带有 @AspectJ 注解 Bean 中解析 Advisor 对象

构造函数

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    /**
     * 用于指定哪些 Bean 能够作为 Advisor
     */
    @Nullable
    private List<Pattern> includePatterns;
    /**
     * 解析 AspectJ 注解的 Advisor 工厂
     */
    @Nullable
    private AspectJAdvisorFactory aspectJAdvisorFactory;
    /**
     * 构建器模式,用于构建  AspectJ 注解的 Advisor
     */
    @Nullable
    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 初始化 BeanFactoryAdvisorRetrievalHelperAdapter
        super.initBeanFactory(beanFactory);
        // 初始化 ReflectiveAspectJAdvisorFactory
        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        // 初始化 BeanFactoryAspectJAdvisorsBuilderAdapter
        this.aspectJAdvisorsBuilder =
                new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }
}

2.1.2 findCandidateAdvisors 方法

findCandidateAdvisors(),该方法会去找符合条件的 Advisor 们,通过父类找到当前 IoC 容器中所有 Advisor 类型的 Bean,这里又会解析出带有 @AspectJ 注解的 Bean 中的 Advisor 们,如下:

protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    // <1> 调用父类方法,从 IoC 容器中查找所有的 Advisor 类型的 Bean
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    // <2> 如果 AspectJ 解析器不为空,默认为 BeanFactoryAspectJAdvisorsBuilderAdapter
    if (this.aspectJAdvisorsBuilder != null) {
        // 解析所有带有 @AspectJ 注解的 Bean
        // 其中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法会被解析成一个 PointcutAdvisor 对象
        // 将解析出来的所有 Advisor 添加至 `advisors` 中
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    // <3> 返回 `advisors` 集合(当前 IoC 容器中解析出来的所有的 Advisor 对象)
    return advisors;
}

该方法的处理过程如下:

  1. 调用父类方法,从 IoC 容器中查找所有的 Advisor 类型的 Bean,保存至 advisors 中,可返回上面的 2.1.1 findCandidateAdvisors 方法 小节查看
  2. 如果 AspectJ 解析器不为空,默认为 BeanFactoryAspectJAdvisorsBuilderAdapter,则通过它解析出 Advisor 来
    • 解析所有带有 @AspectJ 注解的 Bean
    • 其中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法会被解析成一个 PointcutAdvisor 对象
    • 将解析出来的所有 Advisor 添加至 advisors
  3. 返回 advisors 集合(当前 IoC 容器中解析出来的所有的 Advisor 对象)

BeanFactoryAspectJAdvisorsBuilderAdapter

关于 @AspectJ 注解的解析由 BeanFactoryAspectJAdvisorsBuilderAdapter 完成,如下:

// AnnotationAwareAspectJAutoProxyCreator.java
private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {

    public BeanFactoryAspectJAdvisorsBuilderAdapter(
            ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {

        super(beanFactory, advisorFactory);
    }

    @Override
    protected boolean isEligibleBean(String beanName) {
        return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
    }
}

protected boolean isEligibleAspectBean(String beanName) {
    if (this.includePatterns == null) {
        return true;
    } else {
        for (Pattern pattern : this.includePatterns) {
            if (pattern.matcher(beanName).matches()) {
                return true;
            }
        }
        return false;
    }
}

这里只重写了 isEligibleBean(String) 方法,用于判断这个 Bean 是否有资格作为一个 Advisor。可以看到是通过 includePatternsbeanName 进行判断,匹配通过才有资格。当然,includePatterns 一般为空,都有资格。

这个类继承了 BeanFactoryAspectJAdvisorsBuilder 构建器,我们来看到这个构建器是如何解析的。

BeanFactoryAspectJAdvisorsBuilder

org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder,Advisor 构建器,用于解析出当前 BeanFactory 中所有带有 @AspectJ 注解的 Bean 中的 Advisor

构造函数

public class BeanFactoryAspectJAdvisorsBuilder {
    /**
     * 当前 IoC 容器,DefaultListableBeanFactory
     */
    private final ListableBeanFactory beanFactory;
    /**
     * Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor
     */
    private final AspectJAdvisorFactory advisorFactory;
    /**
     * 用于缓存带有 @AspectJ 注解的 Bean 的名称
     */
    @Nullable
    private volatile List<String> aspectBeanNames;
    /**
     * 缓存 @AspectJ 注解的单例 Bean 中解析出来的 Advisor
     * key:带有 @AspectJ 注解的 beanName
     * value:其内部解析出来的 Advisor 集合
     */
    private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
    /**
     * 缓存 @AspectJ 注解的非单例 Bean 的元数据实例构建工厂
     * key:带有 @AspectJ 注解的 beanName(非单例)
     * value:对应的元数据工厂对象
     */
    private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();

    public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
        Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
        Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
        this.beanFactory = beanFactory;
        this.advisorFactory = advisorFactory;
    }
}

2.1.3 buildAspectJAdvisors 方法

buildAspectJAdvisors() 方法,解析出当前 BeanFactory 中所有带有 @AspectJ 注解的 Bean 中的 Advisor,如下:

public List<Advisor> buildAspectJAdvisors() {
    // <1> 从缓存中获取所有带有 @AspectJ 注解的 Bean,保存至 `aspectNames` 集合中
    List<String> aspectNames = this.aspectBeanNames;

    // <2> 缓存中没有,则对当前对象加锁再判断缓存中是否有数据
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            // <3> 还是没有缓存,则进行接下来的处理
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // <3.1> 获取当前 IoC 容器中所有的 Bean 的名称集合
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                // <3.2> 遍历所有的 Bean 的名称,进行处理
                for (String beanName : beanNames) {
                    // <3.3> 判断这个 Bean 是否有资格,默认都为 true
                    if (!isEligibleBean(beanName)) {
                        // 如果没有资格则跳过
                        continue;
                    }
                    // We must be careful not to instantiate beans eagerly as in this case they
                    // would be cached by the Spring container but would not have been weaved.
                    // <3.4> 获取这个 Bean 的 Class 对象,如果为空则跳过
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    // <3.5> 如果这个 Bean 带有 @Aspect 注解,且没有以 `ajc$` 开头的字段,那么进行接下来的解析过程
                    if (this.advisorFactory.isAspect(beanType)) {
                        // <3.5.1>  将这个 Bean 的名称保存至 `aspectNames` 集合中
                        aspectNames.add(beanName);
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        // <3.5.2> 判断 @AspectJ 注解的类别是否为 `singleton`,默认空的情况就是这个
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            MetadataAwareAspectInstanceFactory factory =
                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // <3.5.2.1> 解析这个 Bean 中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法
                            // 会解析成对应的 InstantiationModelAwarePointcutAdvisorImpl 对象(PointcutAdvisor)
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            // <3.5.2.2> 如果这个 Bean 是单例模式,则将解析出来的 Advisor 全部缓存至 `advisorsCache` 中
                            if (this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);
                            }
                            // <3.5.2.3> 否则,将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至 `aspectFactoryCache` 中
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            // <3.5.2.4> 将解析出来的 Advisor 添加至 `advisors` 中
                            advisors.addAll(classAdvisors);
                        }
                        // <3.5.3> 否则,这个 AspectJ 不是单例模式,不能将解析出来的 Advisor 缓存,其他的处理过程都和上面一样
                        else {
                            // Per target or per this.
                            if (this.beanFactory.isSingleton(beanName)) {
                                throw new IllegalArgumentException("Bean with name '" + beanName +
                                        "' is a singleton, but aspect instantiation model is not singleton");
                            }
                            MetadataAwareAspectInstanceFactory factory =
                                    new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            // 将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至 `aspectFactoryCache` 中
                            this.aspectFactoryCache.put(beanName, factory);
                            // 解析出这个 Bean 中所有的 Advisor,并添加至 `advisors` 中
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                // <3.6> 对 `aspectNames` 进行缓存
                this.aspectBeanNames = aspectNames;
                // <3.7> 返回所有 AspectJ 的所有的 Advisor 对象们
                return advisors;
            }
        }
    }

    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    /*
     * <4> 否则,遍历缓存中的 AspectJ 的 beanName
     */
    for (String aspectName : aspectNames) {
        // <4.1> 尝试从 `advisorsCache` 缓存中获取这个 beanName 对应的所有 Advisor 们,并添加至 `advisors` 中
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        // <4.2> `advisorsCache` 缓存中没有,
        // 则根据 `aspectFactoryCache` 缓存中对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)解析出所有的 Advisor 们,并添加至 `advisors` 中
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    // <5> 返回所有 AspectJ 的所有的 Advisor 对象们
    return advisors;
}

该方法的处理过程稍微有点复杂,如下:

  1. 从缓存中获取所有带有 @AspectJ 注解的 Bean,保存至 aspectNames 集合中

  2. 缓存中没有,则对当前对象加锁再判断缓存中是否有数据

  3. 还是没有缓存,则进行接下来的处理

  4. 否则,遍历缓存中的 AspectJ 的 beanName,进行处理

  5. 返回所有 AspectJ 的所有的 Advisor 对象们

做个小结,整个过程稍微复杂一点,会尝试从缓存中获取 Advisor,缓存中没有数据则先获取到所有带有 @AspectJ 注解的 Bean,通过 ReflectiveAspectJAdvisorFactory 对这些 Bean 中带有 AspectJ 相关注解的方法进行处理,生成对应的 PointcutAdvisor 对象。

接下来,我们来看看 ReflectiveAspectJAdvisorFactory 解析 @AspectJ 注解的 Bean 的过程

ReflectiveAspectJAdvisorFactory

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory,Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor

构造函数

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
    /**
     * 方法比较器
     */
    private static final Comparator<Method> METHOD_COMPARATOR;

    static {
        Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
                new InstanceComparator<>( Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                (Converter<Method, Annotation>) method -> {
                    AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                    return (annotation != null ? annotation.getAnnotation() : null);
                });
        Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
        METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
    }
}

可以看到有一个 Comparator 方法比较器,顺序是 @Around > @Before > @After > @AfterReturning > @AfterThrowing,注意获取到应用于某个 Bean 的 Advisor 的顺序不是这样子,可以回到前面的 2.4 sortAdvisors 方法 小节看看

2.1.3.1 getAdvisors 方法

getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) 方法,解析出这个 Bean(带有 @AspectJ 注解)中所有的 Advisor,方法入参是 Bean 的元数据实例构建工厂,方法如下:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // <1> 获取这个 Bean 的 Class 对象和 beanName
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);

    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    // so that it will only instantiate once.
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();

    /*
     * <2> 遍历没有标注 @Pointcut 注解的方法(顺序:@Around > @Before > @After > @AfterReturning > @AfterThrowing)
     */
    for (Method method : getAdvisorMethods(aspectClass)) {
        /*
         * <2.1> 如果这个方法带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解
         * 则根据注解信息创建一个 InstantiationModelAwarePointcutAdvisorImpl 对象
         * 这个对象就是 PointcutAdvisor 类型,包含了 Pointcut 和 Advice
         */
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        // <2.2> 生成了 PointcutAdvisor 则添加至 `advisor` 集合中
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    // <3> 如果这个 Aspect 需要延迟初始化,则往首部添加一个 PointcutAdvisor
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // Find introduction fields.
    // <4> 根据带有 @DeclareParents 注解的字段生成 IntroductionAdvisor 对象,并添加至 `advisor` 集合中
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // <5> 返回这个 Aspect 中所有的 Advisor 对象
    return advisors;
}

该方法的处理过程如下:

  1. 获取这个 Bean 的 Class 对象和 beanName

  2. 遍历没有标注 @Pointcut 注解的方法(顺序:@Around > @Before > @After > @AfterReturning > @AfterThrowing

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
       final List<Method> methods = new ArrayList<>();
       ReflectionUtils.doWithMethods(aspectClass, method -> {
          // Exclude pointcuts
          // 排除 @Pointcut 注解标注的方法
          if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
             methods.add(method);
          }
       });
       // 进行排序
       methods.sort(METHOD_COMPARATOR);
       return methods;
    }
  3. 如果这个 Aspect 需要延迟初始化,则往首部添加一个 SyntheticInstantiationAdvisor(PointcutAdvisor),暂时忽略

  4. 调用 getDeclareParentsAdvisor(..) 方法,根据带有 @DeclareParents 注解的字段生成 IntroductionAdvisor 对象,并添加至 advisor 集合中

    private Advisor getDeclareParentsAdvisor(Field introductionField) {
        DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
        if (declareParents == null) {
            return null;
        }
        if (DeclareParents.class == declareParents.defaultImpl()) {
            throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
        }
        return new DeclareParentsAdvisor(
                introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
    }
  5. 返回这个 Aspect 中所有的 Advisor 对象,也就是返回 advisor 集合

可以看到 @AspectJ 注解的 Bean 中的 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解方法在 getAdvisor(..) 方法中进行

2.1.3.2 getAdvisor 方法

getAdvisor(..) 方法,解析 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解方法,生成 PointcutAdvisor 对象,如下:

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
        int declarationOrderInAspect, String aspectName) {

    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    /*
     * <1> 尝试根据该方法生成一个 AspectJExpressionPointcut 对象
     * 根据 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息进行创建,没有的话则返回 null
     */
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }

    /*
     * <2> 如果存在上面其中一个注解,则将创建的 AspectJExpressionPointcut 封装成 InstantiationModelAwarePointcutAdvisorImpl 对象
     * 也就是封装成了 PointcutAdvisor 对象,会初始化一个 Advice,也就是注解标注的方法
     * 那么这个对象中就包含了 Pointcut 和 Advice,就可以判断某个方法是否被拦截,拦截后应该如何处理
     */
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

该方法的处理过程如下:

  1. 调用 getPointcut(..) 方法,尝试根据该方法生成一个 AspectJExpressionPointcut 对象,根据 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息进行创建,没有的话则返回 null
  2. 如果存在上面其中一个注解,则将创建的 AspectJExpressionPointcut 封装成 InstantiationModelAwarePointcutAdvisorImpl 对象,也就是封装成了 PointcutAdvisor 对象,会初始化一个 Advice,也就是注解标注的方法。那么这个对象中就包含了 Pointcut 和 Advice,就可以判断某个方法是否被拦截,拦截后应该如何处理

getPointcut 方法

getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) 方法,尝试将方法解析成 AspectJExpressionPointcut 对象,如下:

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // <1> 找到这个方法的 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }

    // <2> 如果带有上面其中一个注解,则创建一个 AspectJExpressionPointcut 对象
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    // <3> 设置 Pointcut 的表达式
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    if (this.beanFactory != null) {
        ajexp.setBeanFactory(this.beanFactory);
    }
    // <4> 返回 AspectJExpressionPointcut 对象
    return ajexp;
}

该方法的处理过程如下:

  1. 找到这个方法的 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息
  2. 如果带有上面其中一个注解,则创建一个 AspectJExpressionPointcut 对象
  3. 设置 Pointcut 的表达式
  4. 返回 AspectJExpressionPointcut 对象

getAdvice 方法

getAdvice(..) 方法,主要根据 AspectJExpressionPointcut 初始化一个 Advice 对象,如下:

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);

    // 获取 @Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing 注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }

    // If we get here, we know we have an AspectJ method.
    // Check that it's an AspectJ-annotated class
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }

    if (logger.isDebugEnabled()) {
        logger.debug("Found AspectJ method: " + candidateAdviceMethod);
    }

    AbstractAspectJAdvice springAdvice;

    switch (aspectJAnnotation.getAnnotationType()) {
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        case AtAround: // @Around -> AspectJAroundAdvice
            springAdvice = new AspectJAroundAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtBefore: // @Before -> AspectJMethodBeforeAdvice
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter: // @After -> AspectJAfterAdvice
            springAdvice = new AspectJAfterAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning: // @AfterReturning -> AspectJAfterAdvice
            springAdvice = new AspectJAfterReturningAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing: // @AfterThrowing -> AspectJAfterThrowingAdvice
            springAdvice = new AspectJAfterThrowingAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
            }
            break;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method: " + candidateAdviceMethod);
    }

    // Now to configure the advice...
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    /*
     * 获取方法的参数名列表
     */
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        // 设置参数名
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

根据注解的类型创建对应的 Advice 类型,如下:

  • @Around:AspectJAroundAdvice,实现了 MethodInterceptor
  • @Before:AspectJMethodBeforeAdvice
  • @After:AspectJAfterAdvice,实现了 MethodInterceptor
  • @AfterReturning: AspectJAfterAdvice
  • @AfterThrowing:AspectJAfterThrowingAdvice,实现了 MethodInterceptor

InstantiationModelAwarePointcutAdvisorImpl

org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl,AspectJ 注解方法解析后的对象,实现了 PointcutAdvisor,包含 Pointcut 和 Advice

final class InstantiationModelAwarePointcutAdvisorImpl
        implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {

    private static final Advice EMPTY_ADVICE = new Advice() {};

    private final AspectJExpressionPointcut declaredPointcut;

    private final Class<?> declaringClass;

    private final String methodName;

    private final Class<?>[] parameterTypes;

    private transient Method aspectJAdviceMethod;

    private final AspectJAdvisorFactory aspectJAdvisorFactory;

    private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;

    private final int declarationOrder;

    private final String aspectName;

    private final Pointcut pointcut;

    private final boolean lazy;

    @Nullable
    private Advice instantiatedAdvice;

    @Nullable
    private Boolean isBeforeAdvice;

    @Nullable
    private Boolean isAfterAdvice;

    public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        // AspectJExpressionPointcut 对象
        this.declaredPointcut = declaredPointcut;
        // Advice 所在的 Class 对象
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        // Advice 对应的方法名称
        this.methodName = aspectJAdviceMethod.getName();
        // Advice 对应的方法参数类型
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        // Advice 对应的方法对象
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        // Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        // 元数据实例构建工厂
        this.aspectInstanceFactory = aspectInstanceFactory;
        // 定义的顺序
        this.declarationOrder = declarationOrder;
        // Advice 所在 Bean 的名称
        this.aspectName = aspectName;

        // 如果需要延迟初始化,则不立即初始化 Advice 对象
        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            // Static part of the pointcut is a lazy type.
            Pointcut preInstantiationPointcut = Pointcuts.union(
                    aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

            // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
            // If it's not a dynamic pointcut, it may be optimized out
            // by the Spring AOP infrastructure after the first evaluation.
            this.pointcut = new PerTargetInstantiationModelPointcut(
                    this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
            this.lazy = true;
        }
        // 否则,初始化 Advice 对象
        else {
            // A singleton aspect.
            // AspectJExpressionPointcut 对象
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            // 根据 AspectJExpressionPointcut 初始化一个 Advice 对象
            // `@Around`:AspectJAroundAdvice,实现了 MethodInterceptor
            // `@Before`:AspectJMethodBeforeAdvice
            // `@After`:AspectJAfterAdvice,实现了 MethodInterceptor
            // `@AfterReturning`: AspectJAfterAdvice
            // `@AfterThrowing`:AspectJAfterThrowingAdvice,实现了 MethodInterceptor
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

    private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
        Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
                this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
        return (advice != null ? advice : EMPTY_ADVICE);
    }
}

总结

在上一篇《Spring AOP 自动代理(一)入口》文章讲述了 Spring AOP 自动代理的入口,主要对 AbstractAutoProxyCreator 这个类进行了分析。本文接着上一篇文章分析了在 Spring AOP 自动代理的的过程中,如何从 Spring 上下文筛选出能够应用于某个 Bean 的 Advisor 们,大致的流程如下:

  1. 解析出当前 IoC 容器所有 Advisor 对象

  2. 筛选出能够应用于这个 Bean 的 Advisor 们,主要通过 ClassFilter 类过滤器和 MethodMatcher 方法匹配器进行匹配

  3. 对筛选出来的 Advisor 进行扩展,例如子类会往首部添加一个 PointcutAdvisor 对象

  4. 对筛选出来的 Advisor 进行排序

    • 不同的 AspectJ 根据 @Order 排序

    • 同一个 AspectJ 中不同 Advisor 的排序,优先级:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice

AspectJ 中的注解对应的 Advice 类型如下:

  • @Around -> AspectJAroundAdvice,实现了 MethodInterceptor
  • @Before -> AspectJMethodBeforeAdvice
  • @After -> AspectJAfterAdvice,实现了 MethodInterceptor
  • @AfterReturning -> AspectJAfterAdvice
  • @AfterThrowing -> AspectJAfterThrowingAdvice,实现了 MethodInterceptor

好了,本篇文章就到这里了,如果获取到能够应用于某个 Bean 的 Advisor,那么接下来要做的就是为这个 Bean 创建一个代理对象,通过 JDK 动态代理或者 CGLIB 动态代理,将在下篇文章进行分析。