Spring 源码阅读 74:事务管理的原理 - BeanFactoryTransactionAttributeSourceAdvisor 分析

本文通过对 BeanFactoryTransactionAttributeSourceAdvisor 类的分析,了解了 Spring 是如何通过 AOP 来完成事务的管理的,本文的内容需要你对 Spring 的 AOP 的实现原理有一定的了解。

基于 Spring Framework v5.2.6.RELEASE

概述

Spring 的事务管理基于 AOP 特性,因此,事务管理的增强逻辑需要一个 Advisor 来提供,这便是 BeanFactoryTransactionAttributeSourceAdvisor,本文我们来分析它的原理。

类关系

它是 PointcutAdvisor 的实现类,我们开发时配置的切面通过 Spring 解析后得到的也是一个 PointcutAdvisor,因此,它们的原理应该是相似的。所以,本文会通过以下几个方面来进行分析:

  1. Spring 创建它的具体过程
  2. 如何匹配被增强的类型
  3. 如何匹配被增强的方法
  4. 通过增强逻辑实现事务管理的具体原理

创建

它是在 Spring 解析配置的时候被创建的,以下是 ProxyTransactionManagementConfiguration 中创建 BeanFactoryTransactionAttributeSourceAdvisor 的方法。

// org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
      TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

   BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
   advisor.setTransactionAttributeSource(transactionAttributeSource);
   advisor.setAdvice(transactionInterceptor);
   if (this.enableTx != null) {
      advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
   }
   return advisor;
}
复制代码

方法中,通过无参构造方法创建了 BeanFactoryTransactionAttributeSourceAdvisor 对象,并初始化了一些属性。它并没有显式地声明构造方法,因此我们分别来看几个属性的设置。

transactionAttributeSource 属性

transactionAttributeSource 属性的值,来自方法参数,需要 Spring 来注入,这个值的来源是同一个配置类中的另外一个方法。

// org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration#transactionAttributeSource
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
   return new AnnotationTransactionAttributeSource();
}
复制代码

其中,AnnotationTransactionAttributeSource 的构造方法如下。

public AnnotationTransactionAttributeSource() {
   this(true);
}
复制代码

再进入另外一个构造方法。

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
   this.publicMethodsOnly = publicMethodsOnly;
   if (jta12Present || ejb3Present) {
      this.annotationParsers = new LinkedHashSet<>(4);
      this.annotationParsers.add(new SpringTransactionAnnotationParser());
      if (jta12Present) {
         this.annotationParsers.add(new JtaTransactionAnnotationParser());
      }
      if (ejb3Present) {
         this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
      }
   }
   else {
      this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
   }
}
复制代码

AnnotationTransactionAttributeSource 的构造方法中,主要初始化了两个属性。

  • publicMethodsOnly 的值,从上一段代码的方法调用this(true)传入,它的值是true
  • annotationParsers 是一个列表,根据当前类加载器能够加载到的类型,添加不同的事物注解解析器,限于本文讨论的范围,我们只考虑 SpringTransactionAnnotationParser。

advice 属性

advice 属性的值,同样来自方法参数,它包含的是 Advisor 的增强逻辑,这里注入的值是 TransactionInterceptor 类型,来源也是用一配置类中的另一个方法。

// org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration#transactionInterceptor
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
   TransactionInterceptor interceptor = new TransactionInterceptor();
   interceptor.setTransactionAttributeSource(transactionAttributeSource);
   if (this.txManager != null) {
      interceptor.setTransactionManager(this.txManager);
   }
   return interceptor;
}
复制代码

它的构造方法也不包含任何逻辑,并且,注入了上一部分介绍了 transactionAttributeSource。除此之外,如果成员变量txManager不为空,则赋值给他的 transactionManager 属性。

transactionManager 是事务管理器,可以在当前配置类的父类中,找到它的来源。

TransactionManager

以下就是初始化成员变量txManager的方法。

@Autowired(required = false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
   if (CollectionUtils.isEmpty(configurers)) {
      return;
   }
   if (configurers.size() > 1) {
      throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
   }
   TransactionManagementConfigurer configurer = configurers.iterator().next();
   this.txManager = configurer.annotationDrivenTransactionManager();
}
复制代码

方法添加了 @Autowired 注解,参数是 TransactionManagementConfigurer 类型的集合,Spring 会找到容器中所有的该类型的 Bean,组成一个集合,作为参数执行这个方法的逻辑。

当方法传入的集合中有且只有一个元素的时候,它的annotationDrivenTransactionManager会被执行,并将的到的结果赋值给txManager

以下是 TransactionManagementConfigurer 接口的定义。

public interface TransactionManagementConfigurer {
TransactionManager annotationDrivenTransactionManager();
}
复制代码

里面只有一个方法,返回 TransactionManager 类型的结果,一个配置类可以通过实现 TransactionManagementConfigurer 接口来自定义 TransactionManager 的创建逻辑。

pointcut 属性

除了配置方法中设置的值以外,BeanFactoryTransactionAttributeSourceAdvisor 还有一个定义了初始值的属性pointcut,它表示切入点,负责匹配目标类和目标方法。

// org.springframework.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值