目录
TransactionSynchronizationManager
TransactionSynchronizationManager#registerSynchronization
TransactionSynchronizationAdapter
TransactionSynchronizationManager
有些业务场景涉及到一些操作需要绑定到事务上,比如在事务提交前或事务提交后做一些关联性的操作,这种场景可以使用到org.springframework.transaction.support包路径下的的TransactionSynchronizationManager所支持的同步器实现功能。
实现方式是 在事务方法中调用TransactionSynchronizationManager的registerSynchronization方法注入一个TransactionSynchronization接口实例,通常是使用TransactionSynchronizationAdapter适配器类,然后重写其beforeCommit()或者afterCommit()方法,实现在事务提交前或后执行对应的逻辑。
TransactionSynchronizationManager#registerSynchronization
registerSynchronization()方法入参是一个TransactionSynchronization接口实例,该方法会先判断synchronizations中是否有数据,因为Spring在开启数据库事务时会向其中写入一个实例。
所以这个方法调用必须在事务中执行,否则抛出Transaction synchronization is not active异常
校验通过后就将入参synchronization添加到synchronizations 中。但是注入的synchronization接口实例(TransactionSynchronizationAdapter)中的方法不会立刻执行,而是等到事务执行到一定阶段时才会被调用。
TransactionSynchronization
TransactionSynchronization接口是可以注册到事务处理过程中用于在事务不同状态节点实现同步回调的接口。当事务处理的某些规定时点发生时,会调用TransactionSynchronization上的一些方法来执行相应的回调逻辑,如在事务完成后清理相应的系统资源等操作。
但是TransactionSynchronization接口中没有afterRollback()。所以如果需要在事务回滚后做某些处理,需要在afterCompletion(int status)方法中判断入参的值,然后再做处理。
TransactionSynchronizationAdapter
TransactionSynchronizationAdapter是上面说的TransactionSynchronization接口的一个实例,并为每一个接口方法提供了一个空的实现。其实这种思路跟抽象类有点类似,有了这个空实现的适配器,我们就可以有选择的重写需要处理的回调方法,而不用在业务类中实现接口所有的方法。
使用示例
首先测试一下TransactionSynchronization接口回调方法的执行时机
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
log.error("================afterCommit============");
}
@Override
public void beforeCommit(boolean readOnly) {
log.error("================beforeCommit============");
}
@Override
public void flush() {
log.error("================flush============");
}
@Override
public void beforeCompletion() {
log.error("================beforeCompletion============");
}
@Override
public void afterCompletion(int status) {
if(TransactionSynchronization.STATUS_COMMITTED == status){
log.error("=========afterCompletion======事务提交==============");
}else if(TransactionSynchronization.STATUS_ROLLED_BACK == status){
log.error("========afterCompletion=========事务回滚============");
}
}
});
事务正常提交时执行结果如下,afterCommit方法会被执行
BusinessServiceImpl.java:150) - ================beforeCommit============
BusinessServiceImpl.java:158) - ================beforeCompletion============
BusinessServiceImpl.java:146) - ================afterCommit============
BusinessServiceImpl.java:163) - =========afterCompletion======事务提交==============
当事务发生回滚时结果如下,afterCommit方法不会被执行
BusinessServiceImpl.java:158) - ================beforeCompletion============
BusinessServiceImpl.java:165) - ========afterCompletion=========事务回滚============
下面的代码,方法逻辑是带有事务的更新操作,使用TransactionSynchronizationManager注册一个TransactionSynchronization实例,重写afterCommit方法。可以实现在事务提交后执行afterCommit中发送MQ消息的操作。
@Transactional(rollbackFor = Exception.class)
public void changeStock(Stock stock) {
//事务操作
stockMapper.updateByid(stock);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
producer.sendMessageAync(NOTIFY, vo.getShopMdCode());
}
});
}