好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

spring声明式事务@Transactional底层工作原理

引言

写这篇博文有个来由,是为了解决博主遇到的多数据源的事务问题(用不了JTA),所以深入到spring-tx的源码去学习了一番,非常有收获,最后博主的分布式事务问题也迎刃而解了,这个文章算个开篇,关于如何处理多数据源事务,待下文分解。本文涉及到的技术包含spring aop的使用、spring bean生命周期等,如果能够真正理解Transactional的工作原理,对排查事务相关的问题有非常大的帮助。

spring-tx版本:5.0.2

工作机制简述

先来看一张官方的事务简图:

spring定义了@Transactional注解,基于AbstractBeanFactoryPointcutAdvisor、StaticMethodMatcherPointcut、MethodInterceptor的aop编程模式,增强了添加@Transactional注解的方法。同时抽象了事务行为为PlatformTransactionManager(事务管理器)、TransactionStatus(事务状态)、TransactionDefinition(事务定义)等形态。最终将事务的开启、提交、回滚等逻辑嵌入到被增强的方法的前后,完成统一的事务模型管理。

事务AOP核心类释义

@Transactional

事务注解,用于定位aop的切入点,事务注解里包含了完整事务的所有基本属性,常见的属性如:

transactionManager :事务管理器

propagation :传播行为定义,枚举类型,是spring独有的事务行为设计,默认为PROPAGATION_REQUIRED(支持当前事务,不存在则新建)

isolation :隔离级别,对应数据库的隔离级别实现,mysql默认的隔离级别是 read-committed

timeout :超时时间,默认使用数据库的超时,mysql默认的事务等待超时为5分钟

readOnly :是否只读,默认是false

rollbackFor :异常回滚列表,默认的是RuntimeException异常回滚

TransactionAttribute

事务属性抽象接口类,承载了@Transactional注解里的所有属性,实现类的继承关系如下类结构图,这个实例在被注解解析器创建好后,会在事务上下文中传递

SpringTransactionAnnotationParser

见名知意,这个类是spring的事务注解解析器,实现自TransactionAnnotationParser接口,是spring管理的事务解析器,用于解析@Transactional注解,将注解里的属性设置到TransactionAttribute的实现类属性里。除了这个,另还有两个实现,分别是JTA事务注解解析器,和EJB事务注解管理解析器,区别是解析的注解不同,spring是@Transactional,jta是javax.transaction.Transactional,EJB是javax.ejb.TransactionAttribute。这个地方应用和apache dubbo2.7.x版本解析dubbo的@service注解是一样一样的。关键代码如下,通过AnnotatedElementUtils类,这个类在spring-core包下,找到注解属性集AnnotationAttributes,如果不为空,则包装成事务属性集返回

?

1

2

3

4

5

6

7

8

9

10

11

12

@Override

     @Nullable

     public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {

         AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(

                 element, Transactional. class , false , false );

         if (attributes != null ) {

             return parseTransactionAnnotation(attributes);

         }

         else {

             return null ;

         }

     }

AnnotationTransactionAttributeSource

见名知意,这个类是注解事务属性集的源,怎么理解呢?spring抽象了获取事务属性集的行为,而AnnotationTransactionAttributeSource正是@Transactional注解方式的事务属性集收集实现。SpringTransactionAnnotationParser就是作用于这个里面,用于发现@Transactiona注解的方法

TransactionAttributeSourcePointcut

也是见名知意,Pointcut属于aop的概念范畴,需要了解spring aop的知识才能看明白,这个就是@Transactional注解的切点,AnnotationTransactionAttributeSource作用于此,用于寻找@Transactiona注解的方法,关键代码如下:

?

1

2

3

4

public boolean matches(Method method, Class targetClass) {

         TransactionAttributeSource tas = getTransactionAttributeSource();

         return (tas == null || tas.getTransactionAttribute(method, targetClass) != null );

     }

TransactionInterceptor

事务的拦截器。aop编程里,有了切入点Pointcut,就要有通知advice,我们熟悉的spring aop里有前置、后置、环绕、异常等通知类型,TransactionInterceptor属于自定义通知模型实现,实现自Advice接口,类似于环绕通知,具体见类结构图,如下:

核心方法如下:

?

1

2

3

4

5

6

7

8

public Object invoke(MethodInvocation invocation) throws Throwable {

         // Work out the target class: may be {@code null}.

         // The TransactionAttributeSource should be passed the target class

         // as well as the method, which may be from an interface.

         Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null );

         // Adapt to TransactionAspectSupport's invokeWithinTransaction...

         return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);

     }

被@Transactional注解的方法,如果被aop正确的增强了,运行的时候都会进入到这个方法里面,如果你发现事务不生效啊等等问题,可以从这里开始定位真实原因

BeanFactoryTransactionAttributeSourceAdvisor

事务增强器,用于增强添加了@Transactional注解的方法,上面提到的这些核心类,最终都作用于这里,用于寻找@Transactional注解的方法和织入事务处理逻辑

ProxyTransactionManagementConfiguration

代理事务管理的配置类,上面介绍的这些事务aop编程相关的在这个里面组合配置生效的,同时,如果你有特殊的个性化的需求,也可以自定义注册这个里面的实例。比如我嫌弃@Transactional注解太长了,想用@Tx注解。没关系,直接定义个TransactionAttributeSource实现,解析@Tx的方法,然后注册到spring的上线文中即可。代码如:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

@Configuration (proxyBeanMethods = false )

public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

     @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.getNumber( "order" ));

         }

         return advisor;

     }

     @Bean

     @Role (BeanDefinition.ROLE_INFRASTRUCTURE)

     public TransactionAttributeSource transactionAttributeSource() {

         return new AnnotationTransactionAttributeSource();

     }

     @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;

     }

}

事务抽象核心类释义

PlatformTransactionManager

平台事务管理器,这是Spring事务基础设施中的中心接口。它定义了三个最最基本的事务方法,getTransaction获取事务,包含了事务开启的行为,commit提交事务,rollback回滚事务。代码如下:

?

1

2

3

4

5

6

public interface PlatformTransactionManager extends TransactionManager {

     TransactionStatus getTransaction( @Nullable TransactionDefinition definition)

             throws TransactionException;

     void commit(TransactionStatus status) throws TransactionException;

     void rollback(TransactionStatus status) throws TransactionException;

}

在spring-tx中并没有提供真正的实现类,只提供了一个抽象派生类AbstractPlatformTransactionManager,并建议其他实现基于这个派生类,因为它预先实现了定义的传播行为并处理事务同步处理。子类必须为底层事务的特定状态实现模板方法,例如:begin、suspend、resume、commit等。我们平时常见的实现有:JpaTransactionManager、JtaTransactionManager、DataSourceTransactionManager等。事务管理器和事务aop处理的逻辑本身没有任何耦合,只需将PlatformTransactionManager实例注册到spring上下文中即可,事务拦截器会通过获取到@Transactional里的transactionManager属性去上下文中寻找事务管理器,并将其缓存起来,见TransactionAspectSupport.java里的determineTransactionManager方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

protected PlatformTransactionManager determineTransactionManager( @Nullable TransactionAttribute txAttr) {

         // Do not attempt to lookup tx manager if no tx attributes are set

         if (txAttr == null || this .beanFactory == null ) {

             return asPlatformTransactionManager(getTransactionManager());

         }

         String qualifier = txAttr.getQualifier();

         if (StringUtils.hasText(qualifier)) {

             return determineQualifiedTransactionManager( this .beanFactory, qualifier);

         }

         else if (StringUtils.hasText( this .transactionManagerBeanName)) {

             return determineQualifiedTransactionManager( this .beanFactory, this .transactionManagerBeanName);

         }

         else {

             PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager());

             if (defaultTransactionManager == null ) {

                 defaultTransactionManager = asPlatformTransactionManager(

                         this .transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY));

                 if (defaultTransactionManager == null ) {

                     defaultTransactionManager = this .beanFactory.getBean(PlatformTransactionManager. class );

                     this .transactionManagerCache.putIfAbsent(

                             DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);

                 }

             }

             return defaultTransactionManager;

         }

     }

TransactionStatus

事务状态抽象,用这个类的实现来维护当前的事务状态,spring-tx里提供了默认的实现DefaultTransactionStatus。一般情况下这个不需要我们关心,它和PlatformTransactionManager是成对存在的,心细的你可能已经发现了,PlatformTransactionManager里的三个事务行为传递的就是TransactionStatus。我们知道事务aop增强了添加@Transactional的方法,在执行方法前调用PlatformTransactionManager.getTransaction开启事务,之后调用commit方法提交事务,提交事务的入参TransactionStatus就是开启事务获得的。参见TransactionAspectSupport.java里的createTransactionIfNecessary方法

TransactionDefinition

事务定义,对应了TransactionAttribute,最终通过aop得到的TransactionAttribute里的属性会被传递到TransactionDefinition里,所以TransactionDefinition里也包含了所有事务相关的属性,PlatformTransactionManager.getTransaction正是通过这个里面的属性去获取的事务。AbstractPlatformTransactionManager派生类里也是通过这个里面的属性去判断协调spring的事务传播行为的

结语

当梳理完spring-tx模块的整个结构和工作方式后,仿佛拉开了spring事务管理的面纱,很多事务的执行细节一览无余。很多事务相关的问题也就很容易解释了。比如常见的类中的方法直接调用方法事务不生效等问题,以及可以非常清晰的理解spring的传播行为的真正含义等。最后预告下,spring对于多数据源的事务处理解决方案ChainedTransactionManager

以上就是spring声明式事务@Transactional底层工作原理的详细内容,更多关于spring声明式事务@Transactional工作原理的资料请关注其它相关文章!

原文链接:http://HdhCmsTestkailing.pub/article/index/arcid/281.html

查看更多关于spring声明式事务@Transactional底层工作原理的详细内容...

  阅读:21次