在某些特定的业务场景下,我们可能需要在事务成功提交之后,再做某些操作,而不能将这些操作放在事务代码中,事务还未提交就已经执行了,那这种情况之下,spring提供的TransactionalEventListener就会派上用场了。
使用demo
@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); // 发布事件,等事务commit之后执行 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); } } @Component @Slf4j public class DemoListener { @TransactionalEventListener( phase = TransactionPhase.AFTER_COMMIT, classes = DemoEvent.class) public void onEvent(DemoEvent demoEvent) { log.info("收到事件,事件源是:{}", demoEvent.getSource()); // todo 事务提交后的业务处理 } }
1. 调用DemoService的demo方法时,控制台输出
事务中的业务逻辑执行完毕
收到事件,事件源是:User(name=zhangsan, sex=M, age=30)
2. 如果业务代码中抛出异常,事务回滚,则监听器中的逻辑将不会执行
@Transactional public void demo() { 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方法时,控制台只会输出
事务中的业务逻辑执行完毕