首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spring 事务提交回滚源码解析

前言

在上篇文章

Spring 事务初始化源码分析

中分析了 Spring 事务初始化的一个过程,当初始化完成后,Spring 是如何去获取事务,当目标方法异常后,又是如何进行回滚的,又或是目标方法执行成功后,又是怎么提交的呢?此外,事务的提交和回滚由底层数据库进行控制,而 Spring 事务行为可以传播,这个传播方式由 Spring 来进行控制,它是怎么控制的呢?这篇文章就来分析下 Spring 事务提交回滚的源码。

TransactionInterceptor

还记得在 Spring 事务初始化源码分析 中注册了一个 bean,名字为 吗?,它就是用来执行事务功能的,它是一个方法拦截器,如下所示:

它实现了 接口,而该接口只有一个 方法,用来执行目标方法:

父类的 方法定义了一个事务方法执行的框架,而每一步再细分为方法进行实现,代码如下:

一个事务方法执行流程大概有以下几个步骤:

获取事务属性

获取事务管理器

获取需要事务的方法名称

获取该方法上事务的信息

目标方法执行

事务回滚

清除事务信息

事务提交

获取事务属性

首先去获取方法上面注解的属性,在Spring 事务初始化源码分析已经分析过了,即在

中进行获取。

获取事务管理器

每个事务都有对应的事务管理器,所以在事务开始前需要获取对应的事务管理器

获取需要事务的方法名称

这里主要去获取名称的名称,为 全限定类名+方法名的方式:

获取方法上事务的信息

该部分是 Spring 事务最复杂的部分,比如说去创建一个事务,设置事务的隔离级别,超时时间,对事务传播方式的处理,事务的挂起和恢复等;事务信息 包含了目标方法执行前的所有状态信息,如果方法执行失败,则会根据该信息来进行回滚。

对应方法为:

创建事务

获取事务

在方法 中获取事务,是最为复杂的逻辑,在其中处理隔离级别,超时时间和传播方式等。

获取事务 ,在该方法中,会根据 获取一个连接,如下:

之后,判断当前线程是否存在事务,如果存在事务,则根据事务的传播方式来处理已存在的事务,这里先不看。

如果不存在事务且事务的传播方式为 , ,,则会新建一个事务:

当获取到一个新的事务后,需要设置事务的一些信息,比如隔离级别,timeout 等,这些功能不是由 Spring 来控制,而是由底层的数据库来控制的,数据库连接的设置是在 方法中进行处理:

当设置完事务的信息后,需要把事务信息记录在当前线程中:

现在来处理已经存在事务的情况,

判断是否存在事务,依据是事务中有连接,且 为 true

如果已经存在事务,则会根据事务的传播方式来进行处理,比如 , 等是如何处理:

挂起事务,就是把当前事务的状态记录下来,后续在对该事务进行恢复。

当经过上面一系列操作获取到事务信息后,再根据事务信息来封装到 中:

事务回滚

到这里,目标方法执行之前的事务准备工作都已做好了,之后,会调用 来执行目标方法,如果执行失败,则会进行事务的回滚操作:

回滚事务

事务的回滚操作,如果是嵌套事务,且有保存点的话,直接回滚到保存点,嵌套事务的回滚不会影响到外部事务,也就是说,外部事务不会回滚。回滚到保存点是根据底层数据库来操作的:

如果没有保存点,则直接回滚,也是使用数据库的API 来操作的:

还有一种情况, 如果一个事务中又有事务,如 required, 该事务可以看作一个事务链,那么当其中的一个事务需要回滚的时候,并不是立马进行回滚,而是只是设置回滚状态,到最后再统一回滚。

事务回滚后需要对事务信息进行清除:

清除事务信息:

恢复被挂起的事务:

事务提交

当目标方法执行成功,没有抛出异常,则事务可以正常提交了;但是再上面分析事务回滚的时候,还有一种情况没有分析,就是如果一个事务嵌套再一个事务里面,是一个事务链,如果其中的某个事务需要回滚,它并不会真正的立马进行回滚,而是设置一个回滚标识,由最外层的事务来统一进行回滚;所以再提交事务之前,还需要进行判断。

提交事务:

到这里,Spring 事务的获取,提交,回滚去分析完毕了,流程还是比较清楚的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190121G00CP600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券