好玩Spring之TransactionSynchronization相关的几个类

在看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为了方便我们在事务前后加入自己的一些逻辑而设计了这么个类,有点前置/后置处理器的意思。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值