当前位置:   article > 正文

Spring之AOP源码解析(下)

Spring之AOP源码解析(下)

前言

在上一遍文章中,我们主要讲解了ProxyFactory在Spring完成AOP动态代理的过程中发挥的作用。这一篇我们主要讲解这些注解都是如何注入Advisors,然后分析这些Advisors生效的条件

注解都是如何注入Advisor并匹配的

@EnableTransactionManagement注解

我们在之前提到@EnableTransactionManagement注解会注入一个类型为InfrastructureAdvisorAutoProxyCreator的bpp和事务相关的bean

ProxyTransactionManagementConfiguration这个配置类会注入一个类型为BeanFactoryTransactionAttributeSourceAdvisor的Advisor(以bean的方式注入)

InfrastructureAdvisorAutoProxyCreator这个bpp在执行postProcessAfterInitialization方法的时候会查找可以对bean增强的Advisor,如果找到合适的Advisor则会通过进行aop动态代理

目前这些内容我们在之前的文章中都分析了,现在我们重点关注findAdvisorsThatCanApply这个方法 

 当我们不清楚这个Pointcut是什么类型的时候,可以debug看一下

通过debug我们发现Pointcut是@EnableTransactionManagement注解注入的Advisor的匿名内部类

我们查看这个Advisor的类结构

所以这个Pointcut是一个TransactionAttributeSourcePointcut的一个实例对象

我们再查看TransactionAttributeSourcePointcut的类结构

通过以上分析我们小结一下

  • Pointcut的类型为TransactionAttributeSourcePointcut
  • TransactionAttributeSourcePointcut的过滤器类型为TransactionAttributeSourceClassFilter
  • TransactionAttributeSourcePointcut的MethodMatcher为其自身,并且不等于MethodMatcher.TRUE,且不属于IntroductionAwareMethodMatcher

所以最终我们只需要关注TransactionAttributeSourcePointcut的matches是否能匹配成功

TransactionAttributeSourcePointcut#matcheAbstractFallbackTransactionAttributeSource#getTransactionAttribute AbstractFallbackTransactionAttributeSource#computeTransactionAttributeAnnotationTransactionAttributeSource#findTransactionAttribute 
AnnotationTransactionAttributeSource#determineTransactionAttributeSpringTransactionAnnotationParser#parseTransactionAnnotation

综上所述:@EnableTransactionManagement会注入一个类型为BeanFactoryTransactionAttributeSourceAdvisor的Advisor,当spring处理其他普通bean的时候,这个Advisor就会判断这个bean是否满足自己进行增强的条件(bean含有@Transactional注解标注的方法或者类上含有@Transactional注解),如果满足条件,spring在后期就会进行AOP动态代理

@EnableAspectJAutoProxy注解

从前面两篇文章中我们分析得出@EnableAspectJAutoProxy会注入一个类型为AnnotationAwareAspectJAutoProxyCreator的bpp,这个bpp重写了findCandidateAdvisors方法,我们以这个方法为切入口,分析方法是如何增强的

AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisorsBeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisorsReflectiveAspectJAdvisorFactory#getAdvisorsReflectiveAspectJAdvisorFactory#getAdvisorReflectiveAspectJAdvisorFactory#getPointcutAbstractAspectJAdvisorFactory#findAspectJAnnotationOnMethod

 综上所述:@EnableAspectJAutoProxy注入的bpp会额外查找一些符合条件的Advisor,相关条件如下

  1. bean所属的class上含有@Aspect注解
  2. 存在含有@Around,@Before,@After,@AfterReturning,@AfterThrowing标注的方法

查找出的对象被封装成InstantiationModelAwarePointcutAdvisorImpl,接下来的判断逻辑和@EnableTransactionManagement注解是一致的,都是利用AopUtils的canApply方法,我们需要搞清楚下列几个点,其他细节读者可以自行翻阅源码

  1. InstantiationModelAwarePointcutAdvisorImpl的getPointcut方法返回的是AspectJExpressionPointcut
  2. AspectJExpressionPointcut的getClassFilter方法返回的是自身
  3. AspectJExpressionPointcut的getMethodMatcher方法返回的也是自身
  4. AspectJExpressionPointcut的matches方法的匹配细节

小结

@EnableAspectJAutoProxy注入的bpp通过重写findCandidateAdvisors方法,查找出更多的Advisors,每个Advisor都会通过getPointcut方法返回一个Pointcut对象,Pointcut有两个待实现的方法(getClassFilter、getMethodMatcher),spring会先通过getClassFilter方法返回一个Filter来判断目标类是否满足需求,然后再通过getMethodMatcher方法返回一个MethodMatcher对象,如果MethodMatcher对象等于MethodMatcher.TRUE则直接返回true,否则就获取目标类的相关方法,如果存在一个方法满足MethodMatcher的matches方法,则表示这个Advisor可以作用在这个目标类上。如果存在满足条件的Advisor,spring会在后续进行AOP动态代理

@EnableAsync注解

在前文我们分析得出@EnableAsync会注入一个类型为AsyncAnnotationBeanPostProcessor的bpp,我们查看这个类的类结构,获取一些前提条件

1.无参构造函数

作用:将属性beforeExistingAdvisors设置为true 

2.回调方法setBeanFactory

作用:给属性advisor赋值

AsyncAnnotationBeanPostProcessor作为一个bpp,其主要动态代理相关源码在其祖父类的postProcessAfterInitialization方法中,我们来看看相关明细

小提示:在Spring之AOP源码解析(中)这篇文章中我们分析了,如果通过设置的参数,spring最终决定进行jdk动态代理,则会实现SpringProxy,Advised,DecoratingProxy这三个默认接口,否则会实现SpringProxy,Advised这两个默认接口,所以被spring动态代理的类一定实现Advised接口

我们继续查看这个isEligible方法(通过方法调用,获取最里层方法)

我们又看到这个熟悉的canApply方法,判断流程同上,我们需要知道这个advisor的类型为AsyncAnnotationAdvisor,关注相关方法细节就可以了

我将上述三个注解在Spring中的执行时机用时序图展示出来,便于大家更好的理解

说明一下

  1. 步骤1~6顺序可能不固定,但是最终结果是一样的(存在两个bpp和一个advisor)
  2. 步骤13~14是@EnableTransactionManagement(@EnableAspectJAutoProxy)注入的bpp可能产生的两种结果
  3. 步骤17~18是@EnableAsync注入的bpp对于步骤13可能产生的两种结果
  4. 步骤19~20是@EnableAsync注入的bpp对于步骤14可能产生的两种结果

Spring容器启动后,调用代理对象流程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/143638
推荐阅读
相关标签
  

闽ICP备14008679号