一、本文简介
Spring 中的事务同步管理器是一个非常重要的扩展点,它允许开发者参与到 Spring 管理的事务生命周期中的特定阶段,从而能够在事务开始前、事务结束(提交或回滚)前后执行自定义的操作。这个接口主要用来实现事务相关的同步行为,帮助开发者实现在事务边界上进行资源清理、刷新缓存、发送通知等操作。
二、相关API 介绍
2.1 TransactionSynchronization 介绍
TransactionSynchronization 是一个接口,我们可以通过实现此接口的方法来编写在事务各个阶段要处理的逻辑,下面看下源码,很简单:
public interface TransactionSynchronization extends Flushable {
//提交状态
int STATUS_COMMITTED = 0;
//回滚状态
int STATUS_ROLLED_BACK = 1;
//状态未知,比如事务提交或者回滚的过程中发生了异常,那么事务的状态是未知的
int STATUS_UNKNOWN = 2;
//事务被挂起的时候会调用被挂起事务中所有TransactionSynchronization的resume方法
default void suspend() {
}
//事务恢复的过程中会调用被恢复的事务中所有TransactionSynchronization的resume方法
default void resume() {
}
//清理操作
@Override
default void flush() {
}
//事务提交之前调用,抛出异常会导致整个事务提交失败,回滚事务
default void beforeCommit(boolean readOnly) {
}
//事务提交或者回滚之前调用,进行了try处理,所以无论是否抛出异常,当前事务都会进行提交操作
default void beforeCompletion() {
}
//事务commit成功之后调用
default void afterCommit() {
}
//事务完成之后调用(即,无论是提交还是回滚,事务完就调用)
default void afterCompletion(int status) {
}
}
以上几个方法的执行顺序:
业务代码 -> beforeCommit -> beforeCompletion -> afterCommit -> afterCompletion
方法执行调用逻辑见 AbstractPlatformTransactionManager#processCommit
2.2 TransactionSynchronizationManager
TransactionSynchronizationManager 是一个事务同步管理器,可以用来获取当前事务的状态、信息等。下面源码中只保留了部分常用且重要的API,看完源码就明白它能干什么了
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
//这里是用来存放ConnectHolder
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
//存放事务同步器
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
//存放当前事务的name
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");
/**
* 获取当前线程的数据库资源连接
*
*/
public static Map<Object, Object> getResourceMap() {
Map<Object, Object> map = resources.get();
return (map != null ? Collections.unmodifiableMap(map) : Collections.emptyMap());
}
/**
* 判断当前资源是否存在
* @see ResourceTransactionManager#getResourceFactory()
*/
public static boolean hasResource(Object key) {
//判断当前资源是否存在
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
return (value != null);
}
/**
* 获取当前线程的数据库资源连接
* @see ResourceTransactionManager#getResourceFactory()
*/
@Nullable
public static Object getResource(Object key) {
//获取包装key
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
//获取ConnectHolder
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
/**
* 事务同步器是否还存活
*/
public static boolean isSynchronizationActive() {
return (synchronizations.get() != null);
}
/**
* 常用、重要、关键方法
*
* 用于注册一个TransactionSynchronization对象,该对象包含了在事务的不同阶段(如提交、回滚、完成等)需要执行的逻辑。
* 注册后,当事务到达相应的阶段时,这些逻辑会被自动触发。
*/
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchs.add(synchronization);
}
/**
*
* 返回一个不可修改的列表,其中包含当前线程已注册的所有事务同步器。
*/
public static List<TransactionSynchronization> getSynchronizations() throws IllegalStateException {
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
if (synchs.isEmpty()) {
return Collections.emptyList();
}
else {
// Sort lazily here, not in registerSynchronization.
List<TransactionSynchronization> sortedSynchs = new ArrayList<>(synchs);
AnnotationAwareOrderComparator.sort(sortedSynchs);
return Collections.unmodifiableList(sortedSynchs);
}
}
/**
对于当前线程停用事务同步。
该方法由事务管理器在事务清理时调用。
这句话描述了TransactionSynchronizationManager中的一个操作,即在事务清理时,由事务管理器调用以停用当前线程的事务同步。
这通常发生在事务提交或回滚之后,以确保线程不会继续参与已结束的事务。
停用事务同步意味着清除与事务同步相关的所有状态和资源,以便线程能够安全地参与新的事务。
*/
public static void clearSynchronization() throws IllegalStateException {
if (!isSynchronizationActive()) {
throw new IllegalStateException("Cannot deactivate transaction synchronization - not active");
}
logger.trace("Clearing transaction synchronization");
synchronizations.remove();
}
/**
* 设置事务名
*/
public static void setCurrentTransactionName(@Nullable String name) {
currentTransactionName.set(name);
}
/**
* @see org.springframework.transaction.TransactionDefinition#getName()
* 获取当前事务的名称
*/
@Nullable
public static String getCurrentTransactionName() {
return currentTransactionName.get();
}
/**
* 设置事务只读
*/
public static void setCurrentTransactionReadOnly(boolean readOnly) {
currentTransactionReadOnly.set(readOnly ? Boolean.TRUE : null);
}
/**
*
* 判断当前事务是否只读
*/
public static boolean isCurrentTransactionReadOnly() {
return (currentTransactionReadOnly.get() != null);
}
/**
* 设置事务隔离级别
*/
public static void setCurrentTransactionIsolationLevel(@Nullable Integer isolationLevel) {
currentTransactionIsolationLevel.set(isolationLevel);
}
/**
* 获取当前事务的隔离级别
*/
@Nullable
public static Integer getCurrentTransactionIsolationLevel() {
return currentTransactionIsolationLevel.get();
}
/**
* 设置当前是否有一个实际的活动事务。
*/
public static void setActualTransactionActive(boolean active) {
actualTransactionActive.set(active ? Boolean.TRUE : null);
}
/**
*
* 表示当前是否有一个实际的活动事务。
*/
public static boolean isActualTransactionActive() {
return (actualTransactionActive.get() != null);
}
/**
*
* 清除当前线程的整个事务同步状态:包括已注册的事务同步器以及各种事务特性。
这句话是在描述TransactionSynchronizationManager的一个功能,即清除当前线程中的所有事务同步状态和特性。
这通常发生在事务结束时,以确保线程在下次参与新事务时处于干净的状态。
*/
public static void clear() {
synchronizations.remove();
currentTransactionName.remove();
currentTransactionReadOnly.remove();
currentTransactionIsolationLevel.remove();
actualTransactionActive.remove();
}
}
三、使用案例
比如我们要在某一个业务方法提交成功后发送信息进行通知,这里直接上伪代码了。
1、先创建一个对象TransactionSynchronization,编写发送短信的逻辑
// 创建一个transactionSynchronization 对象,重写afterCommit()方法
TransactionSynchronization transactionSynchronization = new TransactionSynchronizationAdapter(){
// 重写方法,事务提交后执行,发送信息
@Override
public void afterCommit() {
System.out.println(name + ":afterCommit");
// 发送信息相关逻辑
}
}
2、在执行方法的时候注册TransactionSynchronization
@Transactional
public void service(){
// 1. 此处方法业务执行逻辑,操作数据库
// 2.判断当前事务存活,注册一个回调函数
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 注册执行逻辑,在事务提交后会进行消息推送。
TransactionSynchronizationManager.registerSynchronization(transactionSynchronization)
}
}
这个伪代码比较简单,旨在理解用法,我们在实际编码过程中可能会通过切面,事件等方式来进行注册transactionSynchronization ,而不会直接写在业务逻辑方法中。