AI智能
改变未来

死磕Spring之AOP篇 – Spring AOP自动代理(二)筛选合适的通知器

该系列文章是本人在学习 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 动态代理

本文就接着上篇文章来分析筛选合适的通知器的处理过程,包含

@AspectJ

AspectJ

注解的解析过程。这里的“通知器”指的是 Advisor 对象。

回顾

// AbstractAutoProxyCreator.javaprotected 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.javaprotected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,@Nullable TargetSource customTargetSource) throws BeansException;

抽象方法,交由子类实现

筛选出合适的 Advisor 的流程

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

    获取当前 IoC 容器所有 Advisor 类型的 Bean

  2. 解析当前 IoC 容器中所有带有

    @AspectJ

    注解的 Bean,将内部带有

    @Before|@After|@Around|@AfterReturning|@AfterThrowing

    注解的方法解析出对应的 PointcutAdvisor 对象,带有

    @DeclareParents

    注解的字段解析出 IntroductionAdvisor 对象

    @Around

    -> AspectJAroundAdvice,实现了 MethodInterceptor

    @Before

    -> AspectJMethodBeforeAdvice

    @After

    -> AspectJAfterAdvice,实现了 MethodInterceptor

    @AfterReturning

    -> AspectJAfterAdvice

    @AfterThrowing

    -> AspectJAfterThrowingAdvice,实现了 MethodInterceptor

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

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

  • 对筛选出来的 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 检索工具类 */@Nullableprivate BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;@Overridepublic 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 检索工具类为 BeanFactoryAdvisorRetrievalHelperAdapterthis.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);}}

    1. getAdvicesAndAdvisorsForBean 方法

    getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)

    ,筛选某个 Bean 合适的 Advisor,如下:

    @Override@Nullableprotected 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 > AspectJMethodBeforeAdviceeligibleAdvisors = sortAdvisors(eligibleAdvisors);}// <5> 返回排序后的能够应用到当前 Bean 的所有 Advisorreturn 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.javaprotected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");// 借助 BeanFactoryAdvisorRetrievalHelperAdapter 从 IoC 容器中查找所有的 Advisor 对象return this.advisorRetrievalHelper.findAdvisorBeans();}

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

    // BeanFactoryAdvisorRetrievalHelperAdapter.javapublic List<Advisor> findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.// <1> 先从缓存中获取所有 AdvisorString[] 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 是否有资格,默认为 trueif (isEligibleBean(name)) {// <4.2> 正在初始化,则先跳过if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor \'" + name + "\'");}}// <4.3> 否则,获取对应的 Beanelse {try {// 依赖查找到这个 Advisor 对象advisors.add(this.beanFactory.getBean(name, Advisor.class));}catch (BeanCreationException ex) {Throwable rootCause = ex.getMostSpecificCause();// ...throw ex;}}}}// <5> 返回 IoC 容器中所有的 Advisorreturn advisors;}

    该方法的处理过程如下:

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

    2. 没有缓存

      从当前 BeanFactory 容器中找到所有 Advisor 类型的 Bean 的名称

    3. 放入缓存中
  • 如果没有 Advisor,则返回一个空集合

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

      判断这个 Bean 是否有资格,默认为

      true
    1. 正在初始化,则先跳过
    2. 否则,获取对应的 Bean,依赖查找到这个 Advisor 对象
  • 返回 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.javapublic 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 processedcontinue;}// 判断是否能够应用到这个 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.javapublic 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.javapublic 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

      集合中如果不是 java.lang.reflect.Proxy 的子类,则获取

      targetClass

      目标类的 Class 对象(如果目标类是 CGLIB 代理对象,则获取其父类的 Class 对象,也就得到了目标类)

    6. 获取
      targetClass

      目标类实现的所有接口,如果目标类本身是一个接口,那么就取这个目标类

  • 遍历上面的
    classes

    集合

      获取这个 Class 对象的所有方法
    1. 遍历上一步获取到的所有方法
    2. 使用
      methodMatcher

      方法匹配器对该方法进行匹配,优先使用

      introductionAwareMethodMatcher

      方法匹配器,匹配成功则直接返回

      true

      ,说明有一个方法满足条件即可

        AspectJExpressionPointcut 底层就是通过 AspectJ 的表达式处理进行处理的
  • 一个方法都没匹配成功则返回
    false

    ,表示这个 Advisor 不能应用到这个 Bean 上面

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

    2.3 extendAdvisors 方法

    extendAdvisors(List<Advisor> candidateAdvisors)

    放,对筛选出来的 Advisor 进行扩展,抽象方法,我们来看到子类的实现:

    // AspectJAwareAdvisorAutoProxyCreator.java@Overrideprotected 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 requiredif (!advisors.isEmpty()) {boolean foundAspectJAdvice = false;// 遍历所有 Advisorfor (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.javaprotected 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*/@Nullableprivate List<Pattern> includePatterns;/*** 解析 AspectJ 注解的 Advisor 工厂*/@Nullableprivate AspectJAdvisorFactory aspectJAdvisorFactory;/*** 构建器模式,用于构建  AspectJ 注解的 Advisor*/@Nullableprivate BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;@Overrideprotected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 初始化 BeanFactoryAdvisorRetrievalHelperAdaptersuper.initBeanFactory(beanFactory);// 初始化 ReflectiveAspectJAdvisorFactoryif (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}// 初始化 BeanFactoryAspectJAdvisorsBuilderAdapterthis.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 类型的 BeanList<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// <2> 如果 AspectJ 解析器不为空,默认为 BeanFactoryAspectJAdvisorsBuilderAdapterif (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.javaprivate class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {super(beanFactory, advisorFactory);}@Overrideprotected 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。可以看到是通过

    includePatterns

    beanName

    进行判断,匹配通过才有资格。当然,

    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 的名称*/@Nullableprivate 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 是否有资格,默认都为 trueif (!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. 还是没有缓存,则进行接下来的处理获取当前 IoC 容器中所有的 Bean 的名称集合
    4. 遍历所有的 Bean 的名称,进行处理
    5. 判断这个 Bean 是否有资格,默认都为
      true
    6. 获取这个 Bean 的 Class 对象,如果为空则跳过
    7. 如果这个 Bean 带有
      @Aspect

      注解,且没有以

      ajc$

      开头的字段,那么进行接下来的解析过程将这个 Bean 的名称保存至

      aspectNames

      集合中

    8. 判断
      @AspectJ

      注解的类别是否为

      singleton

      ,默认空的情况就是这个通过

      AspectJAdvisorFactory#getAdvisors(..)

      方法解析出这个 Bean 中带有

      @Before|@After|@Around|@AfterReturning|@AfterThrowing

      注解的方法,例如会解析成 InstantiationModelAwarePointcutAdvisorImpl 对象(PointcutAdvisor)

    9. 如果这个 Bean 是单例模式,则将解析出来的 Advisor 全部缓存至
      advisorsCache

    10. 否则,将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至
      aspectFactoryCache

    11. 将解析出来的 Advisor 添加至
      advisors

  • 否则,这个 AspectJ 不是单例模式,不能将解析出来的 Advisor 缓存,其他的处理过程都和上面一样
  • aspectNames

    进行缓存

  • 返回所有 AspectJ 的所有的 Advisor 对象们
  • 否则,遍历缓存中的 AspectJ 的
    beanName

    ,进行处理

      尝试从

      advisorsCache

      缓存中获取这个

      beanName

      对应的所有 Advisor 们,并添加至

      advisors

    1. advisorsCache

      缓存中没有,则根据

      aspectFactoryCache

      缓存中对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)解析出所有的 Advisor 们,并添加至

      advisors

  • 返回所有 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 对象和 beanNameClass<?> 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 需要延迟初始化,则往首部添加一个 PointcutAdvisorif (!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;}

      调用

      getAdvisor(..)

      方法,将这个方法解析成 InstantiationModelAwarePointcutAdvisorImpl 对象(PointcutAdvisor),这个方法必须带有

      @Before|@After|@Around|@AfterReturning|@AfterThrowing

      注解

    3. 如果上一步解析出了 Advisor 对象,则添加至
      advisor

      集合中

  • 如果这个 Aspect 需要延迟初始化,则往首部添加一个 SyntheticInstantiationAdvisor(PointcutAdvisor),暂时忽略

  • 调用

    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());}
  • 返回这个 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 classif (!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 -> AspectJAroundAdvicespringAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtBefore: // @Before -> AspectJMethodBeforeAdvicespringAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfter: // @After -> AspectJAfterAdvicespringAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfterReturning: // @AfterReturning -> AspectJAfterAdvicespringAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;case AtAfterThrowing: // @AfterThrowing -> AspectJAfterThrowingAdvicespringAdvice = 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 InstantiationModelAwarePointcutAdvisorImplimplements 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;@Nullableprivate Advice instantiatedAdvice;@Nullableprivate Boolean isBeforeAdvice;@Nullableprivate 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 中的 Advisorthis.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,实现了 MethodInterceptorthis.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 对象

      获取当前 IoC 容器所有 Advisor 类型的 Bean

    2. 解析当前 IoC 容器中所有带有
      @AspectJ

      注解的 Bean,将内部带有

      @Before|@After|@Around|@AfterReturning|@AfterThrowing

      注解的方法解析出对应的 PointcutAdvisor 对象,带有

      @DeclareParents

      注解的字段解析出 IntroductionAdvisor 对象

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

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

  • 对筛选出来的 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 动态代理,将在下篇文章进行分析。

  • 赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » 死磕Spring之AOP篇 – Spring AOP自动代理(二)筛选合适的通知器