聊一聊Spring中的 Transaction基本实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊一聊Spring中的 Transaction基本实现相关的知识,希望对你有一定的参考价值。

参考技术A 我们知道加一个 org.springframework.transaction.annotation.Transactional 注解便可以让改方法实现事务管理(提交/回滚), 但是我们知道一个如何用编码的方式实现事务如何回滚的 . 抛开动态代理 , 其实事务就是动态代理实现, 但是不是我们的重点 , 我们要讲讲他为啥只支持单个数据源 还有不支持 异步操作(这里的意思是在事务里开启一个新线程执行业务)

一般操作都是下面这样子 , 基本流程

所以Spring帮助我们做的就是这个, 那么它一定也是这么实现的 .

如何启动事务呢 ,

首先需要加入依赖

SpringBoot 可以使用这个 org.springframework.transaction.annotation.EnableTransactionManagement ,对于XML配置可以去看看这个类, 他会教你咋配置 .

方法控制是依靠 @Transactional(transactionManager ="TransactionManager") ,

然后我们需要自己自定义实现一个 org.springframework.transaction.PlatformTransactionManager Bean , 告诉spring事务处理的使用哪个

那么为啥加了个注解就会自动给你管理事务了呢 , 他难道不是这么做的吗.

其实看 org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration 这个地方

在你单数据源的情况下, 同时自动注入情况下, 他会默认给你生成一个 DataSourceTransactionManager

所以默认情况下, 就是走这个, 现在我们绝地不看这个 . 我们要自己实现 .

我们的问题 .

我们定义俩数据源, 其中就需要俩 DataSourceTransactionManager

那么写我们的service

这样子启动绝对会GG , 因为你没指定有哪个 TransactionManager .

那么我们怎么做,

但是事务处理的时候 org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback

他有一个 Connection , 那么不和我们的connection一样 , 那么绝对回滚不了哇. 因为你不是一个连接, 所以根本题绝对提交成功了 , 那么为啥 Mybatis 可以呢 . 所以借鉴一下,

我们看MyBatis的实现 org.mybatis.spring.transaction.SpringManagedTransaction 在这里, 这里缩进不了了 , 他的tab是俩空格, 我是四个, 哎 . 就这么看吧

所以就是在获取这里 DataSourceUtils -> org.springframework.jdbc.datasource.DataSourceUtils#getConnection

doGetConnection(dataSource) -> org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

TransactionSynchronizationManager.getResource(dataSource); -> org.springframework.transaction.support.TransactionSynchronizationManager#getResource

doGetResource(actualKey); -> org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource

其实 resources 就是啥, 就是一个 ThreadLocal 维护的一个线程对象,

所以这就是为啥说事务不支持异步的原因了, 只能一个线程执行一个事务 , 不能俩线程执行 , 比如说这种,绝对不行.

其实到这里我们就拿到了 ConnectionHolder 了 , org.springframework.jdbc.datasource.ConnectionHolder 其实就是一个连接持有者, 一层封装罢了 , 多了一些额外信息.

那么到这里他是如何加入进去的呢, 那就是

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin 这个方法了

org.springframework.transaction.support.TransactionSynchronizationManager#bindResource

所以前前后后就是这个, 所以懂了吗

所以这就是 transaction 的内容 ,

我们观察源码 发现 Transaction 不支持异步操作 , 不支持单任务(单个请求)多数据源, 所以不能保证多数据源的事务相关问题 ,

因此下一期我讲解多数据源 (分库分表其实也是这样子) , 或者 微服务下多数据源问题 .

以上是关于聊一聊Spring中的 Transaction基本实现的主要内容,如果未能解决你的问题,请参考以下文章

深入聊一聊 Spring AOP 实现机制

聊一聊Spring在单例模式下的线程安全

#聊一聊悟空编辑器#spring框架事务相关知识点Spring框架教程

无规矩不成方圆,聊一聊 Spring Boot 中 RESTful 接口设计规范

聊一聊:MyBatis和Spring Data JPA的选择问题

给大家聊一聊云收藏从 Spring Boot 1.0 升级到 2.0 所踩的坑