前言
在分布式系统和复杂业务场景中,我们经常需要在事务完成后执行一些额外操作,比如发送消息通知、更新缓存、记录审计日志等。
事务同步机制概述
事务同步机制是Spring事务管理的重要扩展点,允许我们在事务的不同阶段(如提交前、提交后、回滚后等)执行自定义逻辑。这种机制的核心价值在于:
.保证操作的原子性:确保后续操作仅在事务成功提交后执行
.维护数据一致性:避免事务未完成时外部系统感知到中间状态
.简化业务代码:将事务相关的辅助操作与核心业务逻辑解耦
Spring通过TransactionSynchronization接口定义了事务同步的标准,而TransactionSynchronizationAdapter作为其适配器实现,提供了默认空实现,让开发者只需重写需要的方法,简化了使用成本。
核心方法解析
TransactionSynchronizationAdapter实现了TransactionSynchronization接口,核心方法对应事务生命周期的关键节点:
方法名
|
执行时机
|
典型用途
|
beforeCommit(boolean readOnly)
|
事务提交前
|
最后一次数据校验、设置提交标记
|
afterCommit()
|
事务成功提交后
|
发送消息、更新缓存、调用外部系统
|
afterCompletion(int status)
|
事务完成后(无论成功失败)
|
资源清理、记录最终状态
|
beforeCompletion()
|
事务完成前(提交 / 回滚前)
|
预清理资源、状态记录
|
afterRollback()
|
事务回滚后
|
回滚补偿操作、通知失败
|
代码实现
Repository 接口
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
消息服务(模拟外部系统调用)
@Service
public class MessageService {
/**
* 堆代码 duidaima.com
* 模拟发送欢迎消息
*/
public void sendWelcomeMessage(String email, String username) {
System.out.printf("【消息服务】向 %s(%s) 发送欢迎消息:欢迎注册我们的平台!%n", username, email);
}
/**
* 模拟发送注册失败通知
*/
public void sendRegistrationFailedMessage(String email) {
System.out.printf("【消息服务】向 %s 发送注册失败通知:很抱歉,注册过程出现异常%n", email);
}
}
业务逻辑
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private MessageService messageService;
/**
* 用户注册(带事务同步操作)
*/
@Transactional
public User register(User user) {
// 1. 保存用户(核心业务)
User savedUser = userRepository.save(user);
System.out.println("【用户服务】用户注册成功,ID:" + savedUser.getId());
// 2. 注册事务同步器
registerTransactionSynchronization(savedUser);
// 模拟业务异常(可注释/打开测试事务回滚场景)
// if ("test@rollback.com".equals(user.getEmail())) {
// throw new RuntimeException("模拟注册异常,触发事务回滚");
// }
return savedUser;
}
/**
* 注册事务同步器,定义事务不同阶段的操作
*/
private void registerTransactionSynchronization(User user) {
// 检查当前是否存在事务上下文
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
// 事务提交后执行:发送欢迎消息
@Override
public void afterCommit() {
messageService.sendWelcomeMessage(user.getEmail(), user.getUsername());
}
// 事务回滚后执行:发送失败通知
@Override
public void afterRollback() {
messageService.sendRegistrationFailedMessage(user.getEmail());
}
// 事务完成后(无论成败)执行:记录最终状态
@Override
public void afterCompletion(int status) {
String statusDesc = switch (status) {
case STATUS_COMMITTED -> "已提交";
case STATUS_ROLLED_BACK -> "已回滚";
case STATUS_UNKNOWN -> "未知状态";
default -> "异常状态";
};
System.out.printf("【事务同步】用户 %s 的注册事务最终状态:%s%n", user.getUsername(), statusDesc);
}
});
} else {
throw new RuntimeException("当前无活跃事务,无法注册同步器");
}
}
}
注意事项
事务上下文依赖:必须在活跃的事务上下文中注册同步器(即@Transactional方法内部),否则TransactionSynchronizationManager.isSynchronizationActive()会返回false,导致注册失败。
执行顺序:若注册多个同步器,默认按注册顺序执行。可通过setOrder(int)方法指定执行优先级(值越小越先执行)。
Spring4.2+提供的@TransactionalEventListener是更简洁的替代方案,基于事件机制实现,但TransactionSynchronizationAdapter更灵活,支持更细粒度的事务阶段控制。
@Autowired
private ApplicationEventPublisher publisher;
@Transactional(rollbackFor = Exception.class)
public void add(SomeEntity entity) {
// 业务操作
publisher.publishEvent(entity);
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(SomeEntity entity) {
// 事务提交后执行的逻辑
}