前言
- 在某些特定的业务场景下,我们可能需要在事务成功提交之后,再做某些操作,比如操作成功后发送消息到 MQ 中。
- 不能将这些操作放在事务代码中,会导致事务还未提交就已经执行了,我们需要一种事务提交成功后操作的方法。
- 那这种情况之下,spring 提供的 TransactionalEventListener 就会派上用场了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| @Service @Slf4j public class UserService implements ApplicationEventPublisherAware { private ApplicationEventPublisher eventPublisher;
@Autowired private JdbcTemplate jdbcTemplate;
@Transactional public void demo() {
User user = new User("zhangsan", "M", 30);
eventPublisher.publishEvent(new DemoEvent(user));
jdbcTemplate.update( "insert into t_user (`name`, `sex`, `age`) values (?, ?, ?)", user.getName(), user.getSex(), user.getAge()); log.info("事务中的业务逻辑执行完毕"); }
@Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.eventPublisher = applicationEventPublisher; }}
public class DemoEvent extends ApplicationEvent { public DemoEvent(Object source) { super(source); } }
|
1 2 3 4 5 6 7 8 9 10
| @Component @Slf4j public class DemoListener { @TransactionalEventListener( phase = TransactionPhase.AFTER_COMMIT, classes = DemoEvent.class) public void onEvent(DemoEvent demoEvent) { log.info("收到事件,事件源是:{}", demoEvent.getSource()); }
|
}
调用 DemoService 的 demo 方法时,控制台输出
事务中的业务逻辑执行完毕
收到事件,事件源是:User(name=zhangsan, sex=M, age=30)
如果业务代码中抛出异常,事务回滚,则监听器中的逻辑将不会执行
@Transactional
public void demo() {
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| User user = new User("zhangsan", "M", 30);
// 发布事件,等事务 commit 之后执行 eventPublisher.publishEvent(new DemoEvent(user));
jdbcTemplate.update( "insert into t_user (`name`, `sex`, `age`) values (?, ?, ?)", user.getName(), user.getSex(), user.getAge()); log.info("事务中的业务逻辑执行完毕");
// 模拟业务异常 throw new RuntimeException();
|
}
再次调用 DemoService 的 demo 方法时,控制台只会输出
事务中的业务逻辑执行完毕
使用非常简单,记录一下