本文由 简悦 SimpRead 转码, 原文地址 https://www.jianshu.com/p/1becdc376f5d
前言
事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败。事务具有 4 个特性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Durability(持久性)。在实际开发中,我们对事务应用最多就是在数据库操作这一环,特别是 Spring 对数据库事务进行了封装管理。Spring 对事务的支持,确实很强大,但是从本质上来讲:事务是否生效取决数据库底层是否支持(比如 MySQL 的 MyISAM 引擎就不支持事务,Spring 能奈何!),同时一个事务的多个操作需要在同一个 Connection 上。事务也往往是在业务逻辑层来控制。本篇博客将通过手写一个 Demo 来分析 Spring 事务底层到底是如何帮助我们轻松完成事务管理的!
透彻理解 Spring 事务设计思想之手写实现
先来看一眼工程结构:
ConnectionHolder
在 Spring 中,有时候我们是不是要配置多个数据源 DataSource?很显然,Spring 需要通过 DataSource 来得到操作数据库的管道 Connection,这有点类似于 JNDI 查找。
这里通过 ConnectionHolder 类来完成这个过程,需要思考的是在多线程下,这显然是存在问题的。为避免多线程问题,难道我们采用线程安全的 Map,比如 ConcurrentHashMap,其实我们真正的目的是什么?是保证一个线程下,一个事务的多个操作拿到的是一个 Connection,显然使用 ConcurrentHashMap 根本无法保证!
Spring 很聪明,她提供了一种思路,来解决,看下面的代码!
SingleThreadConnectionHolder
本来线程不安全的,通过 ThreadLocal 这么封装一下,立刻就变成了线程的局部变量,不仅仅安全了,还保证了一个线程下面的操作拿到的 Connection 是同一个对象!这种思想,确实非常巧妙,这也是无锁编程思想的一种方式!
TransactionManager
TransactionManager,这个我们经常在 Spring 里面进行配置吧,事务大管家!
UserAccountDao、UserOrderDao
这里通过这 2 个 DAO,想模拟一个事务中账户购买、下单 2 个操作。
UserService
到这里,可以清晰的看到 Spring 事务管理的一个缩影了吧!
Test
这里,主要是模拟 Spring 的注入以及多用户并发请求。
运行结果
你可以发现,一个线程中的一个事务的多个操作,使用的是同一个 Connection!
好了,到这里,你是否能对 Spring 实现事务的思想有所了解呢?
晚安,早点睡觉,明天继续,O(∩_∩)O 哈哈~