目录
  1. 前言
  2. TransactionSynchronization
  3. 事务同步管理器
  4. 为什么要有事务同步管理器
spring事务(4) 事务同步管理器

前言

spring创建事务的过程中,我们频繁地遇到了一个叫做事务同步管理器的东西。

我在阅读spring源码的过程,总是有这么两个疑惑:

  1. 事务同步管理器是用来做什么的
  2. 为什么要有事务同步管理器

通过阅读源码以及搜集资料,终于得到了这两个问题的答案。

TransactionSynchronization

在spring事务部分有一个这样的接口TransactionSynchronization,我们先来看看这个接口,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface TransactionSynchronization extends Flushable {

int STATUS_COMMITTED = 0;
int STATUS_ROLLED_BACK = 1;
int STATUS_UNKNOWN = 2;

// 挂起
void suspend();

// 恢复
void resume();

@Override
void flush();

// 在事务提交之前调用
void beforeCommit(boolean readOnly);

// 在事务提交/回滚之前调用
void beforeCompletion();

// 在事务提交之后调用
void afterCommit();

// 在事务提交/回滚之后调用
void afterCompletion(int status);
}

可以从接口方法中看出这个方法就是用来在事务执行过程中做一些回调的。那么我一直都很好奇为什么这个接口叫这么一个名字。于是在网上看到了这么一个解释,在事务运行过程中做同步调用,感觉可以接受。

事务同步管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<Map<Object, Object>>("Transactional resources");

private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");

private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<String>("Current transaction name");

private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<Boolean>("Current transaction read-only status");

private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<Integer>("Current transaction isolation level");

private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<Boolean>("Actual transaction active");

在事务同步管理器中,我们可以看到这样一些属性,它们统一使用了ThreadLocal,可以看到同步事务管理器做的工作就是为每个线程管理事务资源以及事务同步等。

事务中的initSynchronization和clearSynchronization方法分别用来激活事务同步以及取消事务同步的激活状态。

为什么要有事务同步管理器

https://www.ibm.com/developerworks/cn/java/j-lo-spring-ts1/index.html这篇文章中看到了一个感觉非常合理的解释。

Web 容器本身就是多线程的,Web 容器为一个 Http 请求创建一个独立的线程,所以由此请求所牵涉到的 Spring 容器中的 Bean 也是运行于多线程的环境下。在绝大多数情况下,Spring 的 Bean 都是单实例的(singleton),单实例 Bean 的最大的好处是线程无关性,不存在多线程并发访问的问题,也即是线程安全的。
一个类能够以单实例的方式运行的前提是“无状态”:即一个类不能拥有状态化的成员变量。我们知道,在传统的编程中,DAO 必须执有一个 Connection,而 Connection 即是状态化的对象。所以传统的 DAO 不能做成单实例的,每次要用时都必须 new 一个新的实例。传统的 Service 由于将有状态的 DAO 作为成员变量,所以传统的 Service 本身也是有状态的。
但是在 Spring 中,DAO 和 Service 都以单实例的方式存在。Spring 是通过 ThreadLocal 将有状态的变量(如 Connection 等)本地线程化,达到另一个层面上的“线程无关”,从而实现线程安全。Spring 不遗余力地将状态化的对象无状态化,就是要达到单实例化 Bean 的目的。
由于 Spring 已经通过 ThreadLocal 的设施将 Bean 无状态化,所以 Spring 中单实例 Bean 对线程安全问题拥有了一种天生的免疫能力。不但单实例的 Service 可以成功运行于多线程环境中,Service 本身还可以自由地启动独立线程以执行其它的 Service。

文章作者: 谷河
文章链接: https://www.lyytaw.com/spring/spring_tx_TransactionSynchronizationManager/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 谷河|BLOG