Spring源码解析(五)-Spring中事物@Transaction原理

@[TOC] spring事物----》 @Transactional
#在上一篇文章中,详细介绍了spring中的AOP的入口和实例化,调用增强相关的基本原理。本篇文章将重点介绍spring中一个重要的AOP:@Transactional注解的修饰的事物切面,事物切面是springAOP切面中的一种切面,所以他也是遵循springAOP切面的一切特点和调用过程,不同的是当前切面的切点和增强的实现不同。在看当前文章前,建议先看一下上一篇文章!!!
https://blog.csdn.net/xqqTechnology/article/details/106897744
这里先了解一下
在 spring 中事务传播属性有如下几种:
PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED 类似的操作。
其中最常见的,用得最多就
PROPAGATION_REQUIRED、
PROPAGATION_REQUIRES_NEW、
PROPAGATION_NESTED 这三种。事务的传播属性是 spring 特有的,是 spring 用来控制方法事务的一种手段,说直白点就是用来控制方法是否使用同一事务的一种属性,以及按照什么规则回滚的一种手段。

part1:@Transactional解析

根据上一篇文章的知识,我们直接来到切面的调用地方进行讲解。
Spring源码解析(五)-Spring中事物@Transaction原理_第1张图片
由于事物切面的advice是TransactionInterceptor,所以,在链式调用的方法中,我们来到advice的入口进入TransactionInterceptor增强实现中。
Spring源码解析(五)-Spring中事物@Transaction原理_第2张图片
在TransactionInterceptor中,的invoke中,会先进行事物调用的解析,然后最后会把火炬进行传递到后面的advice中
Spring源码解析(五)-Spring中事物@Transaction原理_第3张图片
在invokeWithinTransaction中,先回解析@Transaction注解的的属性信息并进行封装
Spring源码解析(五)-Spring中事物@Transaction原理_第4张图片
Spring源码解析(五)-Spring中事物@Transaction原理_第5张图片
解析完成,封装成TransactionAttribute
Spring源码解析(五)-Spring中事物@Transaction原理_第6张图片
然后会获取事物管理器和事物作用的方法
在这里插入图片描述
接下来创建事物createTransactionIfNecessary
Spring源码解析(五)-Spring中事物@Transaction原理_第7张图片
Spring源码解析(五)-Spring中事物@Transaction原理_第8张图片
创建事物,首先会获取事物对象DataSourceTransactionObject,这个事物对象在数据库并不存在,只是spring为了更好的管理事物的提交和回滚封装的一个对象,里面封装了操作数据库的连接池对象
在这里插入图片描述
每次进来,都是新创建事物对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
但是事物对象中的连接对象有可能不一样,有可能一样的
Spring源码解析(五)-Spring中事物@Transaction原理_第9张图片
第一次事物如果传播属性是PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED三种,就会直接进行事物开启,在开启前,先创建了事物状态对象,便于记录事物在执行过程中的一些属性和状态信息
Spring源码解析(五)-Spring中事物@Transaction原理_第10张图片
然后我们来到开启的方法doBegin,
Spring源码解析(五)-Spring中事物@Transaction原理_第11张图片
开启事物后,将当前事物的连接池和连接对象通过ThreadLocal> resources 绑定到当前线程中,便于后面的事物获取第一个事物的连接信息(事物是和连接一一对应的)。
这个 ThreadLocal 中 value 封装了一个 map,map 是数据源对象 DataSource 和连接
对象的映射关系,也就是说,如果上一个事务中建立了映射关系,下一个事务就可以通过当前线程从 ThreadLocal 中获取到这个 map,然后根据当前使用的数据源对象拿到对应的连接对象。然后设置到事务对象中。
在这里插入图片描述
Spring源码解析(五)-Spring中事物@Transaction原理_第12张图片
开启事物后,返回事物状态(封装了当前事物的具体状态信息和连接信息等),
Spring源码解析(五)-Spring中事物@Transaction原理_第13张图片
返回状态信息,封装事务信息对象,创建事务状态对象,事务状态就是记录事务流转过程中状态数据的,有一个数据非常重要,直接决定了提交,回滚和恢复绑定操作,就是 newTransaction 属性,这个属性要牢记。如果为 true 就代表当前事务允许单独提交和回滚,一般是第一次创建事务或者事务传播属性为PROPAGATION_REQUIRES_NEW 的时候。如果为 false 则当前事务不能单独提交和回滚。
Spring源码解析(五)-Spring中事物@Transaction原理_第14张图片
创建事物完成,执行后面的advice获取业务代码
Spring源码解析(五)-Spring中事物@Transaction原理_第15张图片
回滚内部实现:
Spring源码解析(五)-Spring中事物@Transaction原理_第16张图片
提交内部实现:
Spring源码解析(五)-Spring中事物@Transaction原理_第17张图片
上面是一个整体流程,这里介绍一些特殊情况:如果一个事物中包含多个事物调用的代码,第二次事物进来的时候,创建事物的时候,就会执行当前代码,执行
handleExistingTransaction
Spring源码解析(五)-Spring中事物@Transaction原理_第18张图片
Spring源码解析(五)-Spring中事物@Transaction原理_第19张图片
挂起操作就是解除从线程中获取的上个事物的连接对象和当前事物的绑定关系
Spring源码解析(五)-Spring中事物@Transaction原理_第20张图片
挂起事务其实就是把事务对象中的连接对象设置为 null,并且解除 ThreadLocal 的绑定
关系
Spring源码解析(五)-Spring中事物@Transaction原理_第21张图片
Spring源码解析(五)-Spring中事物@Transaction原理_第22张图片
解除后,会返回上一个事物的连接对象
Spring源码解析(五)-Spring中事物@Transaction原理_第23张图片
挂起后,在重新doBegin创建事物
如果第二次进入的事物属性是PROPAGATION_NESTED嵌套事物,则,则会使用上一个事物的连接对象,但是会创建回滚点,便于回滚到指定的地方。在这个代码里面就是用连接对象创建了回滚点,是在方法调用之前创建了回滚点,并且并没有做挂起和开启事务 doBegin 的操作,从这里就能判断当前事务的连接对象和前事务的连接对象是一致的
Spring源码解析(五)-Spring中事物@Transaction原理_第24张图片
前面事务开启已经做完,接下来就是火炬传递了。
如果不清楚事务的不同传播属性的流转,建议可以采用伪代码的方式来分析:
transation 方法
createTransactionIfNecessary = 开启事务
try {
addArea 方法
开启事务
Try{
目标类 addArea 调用
}catch(Throwable ex) {
事务回滚?
throw ex;
}
commitTransactionAfterReturning
addArea 方法提交事务?
addGoods 方法
开启事务
Try{
目标类 addGoods 调用
Throw new RuntimeException();
}catch(Throwable ex) {
事务回滚?
throw ex;
}
commitTransactionAfterReturning
addGoods 方法提交事务?
}catch (Throwable ex) {
completeTransactionAfterThrowing = 事务回滚
throw ex;
}
transation 方法提交事务
commitTransactionAfterReturning = 事务提交
后面还会持续更新spring相关源码讲解,敬请期待!!!

你可能感兴趣的:(Spring源码解析(五)-Spring中事物@Transaction原理)