《Spring揭秘》读书笔记四:统一事务管理
一、背景和支撑
事务代码混在业务代码之中,不便于维护。基于上一章介绍的 AOP可以想到,通过AOP的方式 将 Spring事务从 业务代码中剥离出来。
自己实现的话:声明一个注解,然后通过 AOP的 @annoation的 Pointcut 为 带有 自定义注解的方法 加入事务逻辑即可。
二、Spring 统一的方式
事务有多种实现,Spring 统一抽象出了 PlatformTransactionManager,然后 根据具体的使用场景提供具体的 实现即可。
图来自《Spring揭秘》
总体上使用 策略模式,具体实现类上 使用了 模板方法模式。
AbstractPlatformTransactionManager编写出了通用的事务模板,大体按照如下步骤:
1、检查当前是否存在事务
2、根据 Transaction中的 传播行为 做出相应的举动
3、提交前检查 TransactionStatus 中的 RollBackOnly状态,判断是否需要用 回滚代替提交
4、回滚后,清理并恢复事务装填
三、具体使用
编程式和声明式
声明式,除了加上 @Transactional注解之外, 还需要提供 具体的 PlatformTransactionManager,Spring boot 会 自动为我们注册到容器,不用我们做额外的处理。
四、ThreadLocal
JDBC事务基于 Connection,所以 一次事务中的 所有数据操作都需要使用 同一个 Connection,如果在多个方法之间进行 Connection的传递,方法的复用性和耦合性无疑很差。
此时, 我们可以使用 ThreadLocal的方式,将Connection对象绑定到线程中,这样 各个方法直接从线程中获取 Connection即可。
ThreadLocal的原理:实际的内容是 存储在 Thead对象的 ThreadLocalMap之中, ThreadLocal对象只是作为存储时的 key而已。
常见的使用场景:
1、诸如 SimpleDateFormat之类的 线程不安全的对象,不可以作为类变量共享于各个实例之间,可以 通过 ThreadLocal构造线程的私有变量,每个线程都持有一个 独立的对象,可以保证线程安全性。
2、线程安全的对象,声明为 一个类变量在 多个线程之间共享,多个线程发生竞争有可能造成 性能的损失。此时,我们也可以 构造线程私有变量来提高性能。
3、可以使用 ThreadLocal 将数据绑定到线程,以比较解耦的方式传递在各个方法间 传递数据。但是此种方法需要注意的是:
要适时的 绑定以及解绑。原因在于,框架中普遍使用 线程池技术,线程是一直存在的,可能造成数据的混乱,需要在一开始绑定数据,流程结束了 记得 清空数据。