在看Spring事务源码时,会看到TransactionSynchronizationManager这个类的几个方法,当时不知这个类有何作用,于是,单独研究了一番,与TransactionSynchronization相关的有如下几个类:
TransactionSynchronization
public interface TransactionSynchronization extends Flushable {
/** Completion status in case of proper commit. */
int STATUS_COMMITTED = 0;
/** Completion status in case of proper rollback. */
int STATUS_ROLLED_BACK = 1;
/** Completion status in case of heuristic mixed completion or system errors. */
int STATUS_UNKNOWN = 2;
default void suspend() {
}
default void resume() {
}
@Override
default void flush() {
}
default void beforeCommit(boolean readOnly) {
}
default void beforeCompletion() {
}
default void afterCommit() {
}
default void afterCompletion(int status) {
}
}
接口中定义的这些方法,在实现类中不一定都需要,肿么办?于是Spring惯用的适配器,又出来了。
TransactionSynchronizationAdapter
public abstract class TransactionSynchronizationAdapter implements TransactionSynchronization, Ordered {
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public void suspend() {
}
@Override
public void resume() {
}
@Override
public void flush() {
}
@Override
public void beforeCommit(boolean readOnly) {
}
@Override
public void beforeCompletion() {
}
@Override
public void afterCommit() {
}
@Override
public void afterCompletion(int status) {
}
}
这个类,就是为了不用在业务类中放大量无用的接口方法,只需按需重写方法即可。
TransactionSynchronizationManager
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
// 事务资源:map<k,v> 两种数据对。
// 1.会话工厂和会话k=SqlsessionFactory v=SqlSessionHolder
// 2.数据源和连接k=DataSource v=ConnectionHolder
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
//事务同步器,是Spring交由程序员进行扩展的代码,每个线程可以注册N个事务同步器。
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
// 事务的名称
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
// 事务是否是只读
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
// 事务的隔离级别
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
// 事务是否开启
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
...
省略代码
...
}
该类主要是对以上这几种ThreadLocal资源的操作,在这个类中,我认为其中有3个方法比较重要。
bindResource()
在事务由挂起状态恢复正常时,其实就是绑定对应的Map<DataSource,ConnectionHolder>绑到当前线程中
public static void bindResource(Object key, Object value) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Assert.notNull(value, "Value must not be null");
Map<Object, Object> map = resources.get();
// set ThreadLocal Map if none found
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
Object oldValue = map.put(actualKey, value);
// Transparently suppress a ResourceHolder that was marked as void...
if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
oldValue = null;
}
if (oldValue != null) {
throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
if (logger.isTraceEnabled()) {
logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
Thread.currentThread().getName() + "]");
}
}
在事务挂起时,对应的就是解绑操作。
doUnbindResource()
private static Object doUnbindResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
Object value = map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
// Transparently suppress a ResourceHolder that was marked as void...
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
value = null;
}
if (value != null && logger.isTraceEnabled()) {
logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
关于资源的绑定与解绑,在之前好玩Spring之Transactional注解是如何工作的 博客中,事务挂起与恢复中也有提到,可以结合着看。
registerSynchronization()
这个方法帮助我们在事务commit/completion前后进行一些自定义的操作。
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
if (!isSynchronizationActive()) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchronizations.get().add(synchronization);
}
比如下面的例子
@Transactional(transactionManager = "txManager")
public void add() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
connection.setAutoCommit(false);
jdbcTemplate.execute("insert into test(title, author) values('title1', 'author1')");
} catch (SQLException e) {
e.printStackTrace();
}
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void beforeCommit(boolean readOnly) {
System.out.println("Do something befor commit...");
}
@Override
public void afterCompletion(int status) {
System.out.println("Do something after completion...");
}
});
System.out.println("Method complete...");
}
输出结果
Method complete...
processCommit start... // AbstractPlatformTransactionManager类中commit流程开始
Do something befor commit...
Execute transaction commit... // commit动作执行
Do something after completion...
processCommit end... // AbstractPlatformTransactionManager类中commit流程结束
从结果可以看出,TransactionSynchronizationManager由另外的线程执行,并且分别在commit之前,和completion后执行了我们的业务。
TransactionSynchronizationUtils
这个类就不介绍了,工具类主要实现了一些操作的封装。
总结
之前看源码时,光从字面来看这几个类,真是没明白是干嘛的,现在来看,其实还是Spring为了方便我们在事务前后加入自己的一些逻辑而设计了这么个类,有点前置/后置处理器的意思。