记得以前我做过一个需求,当时我做的项目负责管理公司所有的用户信息和机构信息,里面有一个细节,就是增删改查用户的接口都需要发送MQ消息以便可以通知下游项目(他们可能依赖这个做一些缓存的清理),直到有一天,一个开发小哥找到我,我才知道我在项目里埋了一个雷,我把保存数据的操作和发送MQ消息的操作都封装在了@Transactiona 修饰的方法里了,这导致了一个很明显的问题,就是事务还没有提交,我的消息就发送出去了,然后下游收到通知后又来调用我的接口获取最新的信息,结果发现获取的信息依然没有变化。
后来我就用了下面方案一的方法解决了这个问题。
方案一:
其实也很简单,就是把发送MQ消息的代码从方法内移出去了,确定事务提交后再发消息,虽然可以实现功能,但是总觉得不是很优雅,毕竟我是一个仪式感满满的程序员。
方案二:
经过长时间的找寻,无意间发现了一个更加优雅的写法,完美的解决了我的需求。
先上图:
看到了吗?
事务已经提交了,但是断点还在方法里,通过这个afterCommit方法,我们可以在这里发送我们的MQ消息,终于不用把一个方法拆成两个写了。
总结:
其实我们用到的是这个类,事务同步器
TransactionSynchronizationManager
当我们在事务执行前后可能需要做一些额外的操作这个时候我们就需要用到TransactionSynchronizationManager去注入一个TransactionSynchronization事务同步器,然后重写TransactionSynchronization或者其子类的beforeCommit()或者afterCommit()方法,写入我们需要执行的业务。