2018-08-13事物回调采坑
事件还原,最近在做一个项目,然后在提测阶段,测试提出说imei数据没有同步。远程断点排查少不了,发现有个事物回调方法sendImeiSynMsgByCount,会在事物成功提交后,回调afterCommit()方法发送mq消息同步imei数据。发现afterCommit方法最后会被调用,只是其中的imeiCenterPOList参数值为空了,所以不会发送mq消息了。部分代码如下
咦,为什么参数会莫名其妙的不见了,难道是异步事物回调的时候会把参数清理掉了?没辙,事物回调方法继续打断点,跟踪下事物回调源码。
第一次调试的时候,发现TransactionSynchronizationManager.getSynchronizations()里是有回调参数imeiCenterPOList的。但是这时候并没有触发invokeAfterCommit,因为没有满足条件,事物回调只有在事物成功提交后才会触发。可是明明已经走完了batchAddImei方法,而且没有抛出异常,按道理应该会成功提交事物的。看下外部调用,果然外部方法里也做了事物注解。
继续断点,发现还是没有触发,而且这时候TransactionSynchronizationManager.getSynchronizations()里依然是有回调参数imeiCenterPOList的。继续向外找方法调用,果然最外层还嵌套了一层注解事物。断点后发现,invokeAfterCommit触发了,但是这时候TransactionSynchronizationManager.getSynchronizations()的回调参数imeiCenterPOList的值变为0了。
我们都知道注解式事物Propagation.REQUIRED是存在则继承,不存在则创建的。所以最终的事物提交需要等最外层事物提交后,才会触发事物提交。然后看下最外层方法是不是对imeiCenterPOList参数有操作,最后发现如下有个clear清理逻辑。终于找到罪魁祸首。
最后解决:在sendImeiSynMsgByCount调用事物回调方法时,做参数复制。