一、前言
我们一般在使用spring的监听器,会使用@EventListener
来实现同步监听事件。但是这种存在一个问题,当前事务是没有提交的。如果需要在执行事件之前将事务提交,可以使用@TransactionalEventListener
来实现监听方式。
二、@TransactionalEventListener重要的参数
phase: 将事件的处理与事务执行阶段绑定。默认是TransactionPhase.AFTER_COMMIT,也就是事务提交后执行。如果没有正在进行的事务,则完全不处理事件,除非显式启用了fallbackExecution。
fallbackExecution:这里默认值为false,含义是如果当前没有事务控制,例如不存在@Transactional,事件就不会执行。
三、@EventListener与@TransactionalEventListener对比案例
拿用户注册举例,用户注册成功短信通知用户。见下面的代码。
- register
@Transactional(rollbackFor = Exception.class)
public void register(String username) {
// ... 执行注册逻辑
log.info("[register][执行用户({}) 的注册逻辑]", username);
String sql = String.format("insert into sys_user(username) values ('%s');", username);
jdbcTemplate.execute(sql);
// 注册成功通知
applicationEventPublisher.publishEvent(new UserRegisterEvent(this, username));
}
】
- SmsService
@Slf4j
@Service
public class SmsService {
@Autowired
private JdbcTemplate jdbcTemplate;
@EventListener
public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
String sql = String.format("select * from sys_user where username = '%s';", userRegisterEvent.getUsername());
Map<String, Object> map = jdbcTemplate.queryForMap(sql);
// 可以将断点打点这个地方,查询数据库数据提交情况
log.info("用户注册成功:{}。发送短信消息,username:{}", map, userRegisterEvent.getUsername());
}
}
此时,数据库是无数据的。
将@EventListener改为@TransactionalEventListener
此时再查询数据库,可以看到事务是已经提交的了。