JavaWeb技术程序员

Spring事务

2019-03-30  本文已影响0人  不知名的程序员

Spring AOP原理分析介绍了AOP的一些细节,有了这篇文章的基础,我们再来分析Spring中声明式事务的实现就能够轻车熟路一些。

一些概念

事务可以分为2种,全局事务与本地事务。

全局事务可以保证多数据源下的事务特性(关于事务的ACID特性这里不详说),本地事务则可以保证单个数据源下的事务特性。全局事务使用JTA,支持多事务源事务(通过XA协议来支持,然而XA性能较低,一般都会采取别的分布式事务方案,比如事务消息,补偿方案等);本地事务则基于JDBC连接,不支持分布式事务。

事务管理器

Spring使用事务管理器来管理事务,下面的接口是Spring事务管理器的统一抽象接口,我们可以根据需要实现自己的事务管理器。Spring提供了许多事务平台默认的实现,比如基于JDBC的DataSourceTransactionManager,基于JTA的JtaTransactionManager,基于Hibernate的HibernateTransactionManager等。

其中getTransaction(..)方法根据TransactionDefinition参数返回一个TransactionStatus对象。如果当前调用堆栈中存在匹配的事务,则返回的TransactionStatus可能表示一个新事务,也可能表示一个现有事务,由TransactionDefinition来决定。

TransactionDefinition

TransactionDefinition定义了很多常量,代表着不同的含义

以Propagation开头的代表传播行为:在事务范围内执行的所有代码都在该事务中运行,但是,如果事务方法在事务上下文已经存在时执行,则可以指定行为。例如,代码可以在现有事务中继续运行(通常情况下),或者可以挂起现有事务并创建一个新事务

以Isolation开头的代表隔离程度:即事务的隔离级别

getTimeout方法:获取事务的超时时间

isReadOnly方法(只读状态):是否为只读状态

getPropagationBehavior方法:获取传播行为

getIsolationLevel:获取隔离程度

传播行为与隔离级别

由接口中的常量可知,共有7种传播行为,分别为:

REQUIRED:如果当前范围不存在事务,则新建一个事务(默认)

REQUIRES_NEW:总是新建一个事务。

NESTED:如果当前有事务,则在嵌套事务内执行,如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。仅适用于JDBC事务,本质上是根据JDBC回滚点回滚指定范围内的操作,NESTED和REQUIRES_NEW都可以做到内部方法事务回滚而不影响外围方法事务。但是因为NESTED是嵌套事务,所以外围方法回滚之后,作为外围方法事务的子事务也会被回滚。而REQUIRES_NEW是通过开启新的事务实现的,内部事务和外围事务是两个事务,外围事务回滚不会影响内部事务

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

一般情况下我们使用默认的传播行为即可。

隔离级别对应的就是数据库的隔离级别,其中有个DEFAULT,代表着默认的隔离级别,他是跟着底层数据库变化的,例如如果是MySQL的话,那么默认的隔离级别就是可重复读。

声明式事务

Spring中事务管理分为编程式事务与声明式事务,Spring官方建议使用声明式事务进行事务管理,对代码侵入性较小。

声明式事务执行流程

回滚:默认情况下,Spring只对RunTimeException与Error类型的异常进行回滚,我们也可以指定发生某些异常不会滚或者发生某些异常回滚

声明式事务使用@Transactional来实现,由于Spring中事务由代理实现,所以AOP的问题事务管理同样会有:应该只将@Transactional应用于public方法。如果使用@Transactional注释private,事务并不会生效。在代理模式(这是缺省模式)中,只拦截通过代理传入的外部方法调用。这意味着自调用(实际上,目标对象中的一个方法调用目标对象的另一个方法)不会在运行时执行事务,即使被调用的方法被标记为@Transactional。

源码分析

同Spring AOP一文的分析类似,开启事务的注解为@EnableTransactionManagement,从该注解开始分析。

如果是代理模式(默认)则导入AutoProxyRegistrar与ProxyTransactionManagementConfiguration俩个组件。

AutoProxyRegistrar类中最终注册了InfrastructureAdvisorAutoProxyCreator。

InfrastructureAdvisorAutoProxyCreator是一个后置处理器,我们找到后置处理器相关的接口,在对象创建以后,将对象包装成代理对象返回

ProxyTransactionManagementConfiguration类注册了BeanFactoryTransactionAttributeSourceAdvisor与AnnotationTransactionAttributeSource

AnnotationTransactionAttributeSource中的各种TransactionAnnotationParser负责解析事务相应的注解。

另一个bean为TransactionInterceptor事务拦截器,其中保存了事务的属性与事务管理器

找到动态代理相关的实现类,查看invoke方法

接上图

如果是事务方法则会进入到createTransactionIfNecessary方法开始一个事务,invocation.proceedWithInvocation();执行方法中操作。

如果发生异常则调用completeTransactionAfterThrowing(txInfo, ex);

判断注解中是否指定了回滚的异常,根据异常做相应的回滚操作

最后调用commitTransactionAfterReturning(txInfo);进行事务的提交。

总结:找到被事务注解注释的相关bean,为bean生成代理对象,在对象方法执行时执行代理对象的invoke方法,做相应的事务操作。总体流程和AOP是一样的。

上一篇下一篇

猜你喜欢

热点阅读