Mybatis事务源码

使用

<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

dataSource参数

事务自定义标签
该命名空间肯定有对应的handler来进行调用相应的解析器来执行。
在这里插入图片描述
AnnotationDrivenBeanDefinitionParser类的parse方法
在这里插入图片描述

AopAutoProxyConfigurer.configureAutoProxyCreator这个默认方法
在这里插入图片描述

看到这里,代码就是为TransactionAttributeSourceAdvisor这个bean中两个属性设置成TransactionAttributeSource和TransactionInterceptor。

第一行注册了一个InfrastructureAdvisorAutoProxyCreator
在这里插入图片描述

再来看下InfrastructureAdvisorAutoProxyCreator这个类。
在这里插入图片描述
InfrastructureAdvisorAutoProxyCreator继承了BPP接口,意味着是在初始化后对其需要的bean进行封装成代理对象。
在这里插入图片描述
这里的流程之前文章介绍了,我再来回顾一下吧。通过这个bean找出对应的增强方法,然后调用createProxy方法创建出来代理对象。

寻找所有的增强方法-BeanFactoryUtils.beanNamesForTypeIncludingAncestors
在这里插入图片描述
这里的Advisor类,可以让我们想到之前注册的TransactionAttributeSourceAdvisor也是Advisor增强方法,自然获取的时候会获取到。
在这里插入图片描述
TransactionAttributeSourceAdvisor实现了PointcutAdvisor接口
在这里插入图片描述
第一个参数pointcut返回的TransactionAttributeSourcePoint类型的实例,该实例里头有getTransactionAttributeSource方法。
在这里插入图片描述
寻找该类时候的增强方法流程:先对所有增强方法进行循环,遍历过程中对类的方法再次遍历,查找匹配成功的增强方法。
在寻找相应增强方法流程中,需要提取事务标签。

提取事务标签computeTransactionAttribute
这里method代表接口中的方法,specificMethods代表实现类中的方法。
在这里插入图片描述
先看方法上是否存在事务属性,存在则使用方法上的属性,否则使用方法所在类上的属性,没找到,则搜索接口方法中的属性,再没有搜索到,最后尝试接口的类上面的声明。
findTransactionAttribute方法就是用来解析我们声明的属性,propagation、isolation、readOnly等等。
在调用事务增强器增强的代理类时会首先执行TransactionInterceptor进行增强,同时调用invoke方法完成整个事务的逻辑

事务增强器TransactionInterceptor的invoke方法-在代理类执行相应方法时调用
在这里插入图片描述
invokeWithinTransaction方法
在这里插入图片描述
执行事务流程
1.获取事务属性(在将类转为代理类时,已经提取了事务属性,上面描述了)
2.加载配置中的TransactionManager
3.不同的事务处理方式使用不同的逻辑。声明式事务便于理解。
4.在目标方法执行前获取事务并收集事务信息。TransactionInfo中包含TransactionAttribute,所以事务信息和事务属性并不相同。TransactionInfo还包括PlatformTransactionManager以及TransactionStatus相关信息。
5.执行目标方法
6.一旦出现异常,尝试异常处理。
7.提交事务前的事务信息清除。
8.提交事务。

接下来看一下事务创建的过程-创建事务信息
在这里插入图片描述
getTransaction方法用于获取事务

看下doGetTransaction方法
在这里插入图片描述
看一下事务传播行为,可以看到MANDATORY在没有事务时会抛出异常。
在这里插入图片描述
紧接着doBegin方法处理数据库连接设置-个人认为是获取新事务
在这里插入图片描述

事务准备工作流程getTransaction方法
1.获取事务 doGetTransaction方法。
2.如果当前线程存在事务,则转向嵌套事务的处理handleExistingTransaction。
3.事务超时设置验证
4.事务getPropagationBehavior传播行为的一些验证
5.构建DefaultTransactionStatus
6.完善transaction,包括设置ConnectionHolder、隔离级别、timeout。如果是新连接,绑定到当前线程。
在这里插入图片描述
doBegin方法流程
1.如果不存在connectionHolder则尝试获取新连接,如果当前线程已经存在connectionHolder,则没必要再次获取(之前判断过线程是否有连接并且是否存在事务。如果没有事务的话,可能会进来,直接用原来的连接)。对于事务同步表示设置为true的需要重新获取连接。
2.DataSourceUtils.prepareConnectionForTransaction中设置了隔离级别并给connection设置只读标识。
3.更改默认的提交设置
4.设置标志位,标识当前连接已被事务激活。
5.设置过期时间。
6.将connectionHolder绑定到当前线程。

当存在事务情况下会执行handleExistingTransaction方法,挂起使用suspend方法
在这里插入图片描述
当建立事务连接并完成事务信息的提取后,将事务信息统一记录在TransactionInfo实例中。包含了目标方法一开始的所有状态信息。

回滚处理completeTransactionAfterThrowing
抛出异常时会先判断是否存在事务,如果存在事务调用rollbackOn方法判断是否是RuntimeException或者Error类型,如果是这些类型,那么可以进行回滚,如果不是那么进行提交并抛出异常。如果不存在事务,什么都不用管。
在这里插入图片描述
回滚处理的大致实现
在这里插入图片描述
1.首先是自定义触发器的调用,包括在回滚前、完成回滚后的调用。
2.当之前已经保存的事务信息中有保存点信息,使用保存点信息进行回滚。常用于嵌套式事务。 内嵌的事务不会引起外嵌的回滚。
当之前已经保存的事务信息中事务为新事务,那么直接回滚。在里头会调用connection的rollback方法。
在这里插入图片描述
3.回滚后的信息清除。设置完成表示避免重复调用
4.如果事务执行前有事务挂起,那么当事务执行结束需要将挂起的事务恢复。
在这里插入图片描述
最后是事务提交commitTransactionAfterReturning方法
在这里插入图片描述
在提交的过程并不是直接提交的,而是考虑很多种情况。主要是因为嵌套事务情况。Spring将嵌套事务开始之前设置保存点,一旦嵌套事务出现异常便会回滚。但如果没有出现异常,内嵌事务也不会提交,而是由外层事务负责提交。
1.当事务状态中有保存点信息的话,不去提交。
2.如果非新事务,也不会执行提交。(如果有事务,在该事务中允许,就是非新事务吧)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值