@Transactional事務提交後觸發異步方法

一、問題復現

1.場景

2個service方法, 方法A中調用方法B。

方法A 是核心業務方法,涉及多張表數據變更,爲了保持數據一致,用spring事務註解:@Transactional(rollbackFor = Exception.class)

方法B 比較耗時,爲了不影響核心業務,方法B 用@Async註解,單獨開啓一個線程去異步執行。(方法B在另外一個類裏邊,不能和A在同一個類)。

2.出錯原因

方法B是異步方法,導致方法A事務還沒提交時(不一定出錯,具體就看哪個線程執行的快了)方法B就執行了。

3.期望

期望方法A上的大事務commit後再執行方法B。

 

二、解決方案

 

1 // 註冊事務同步處理
2 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
3 @Override
4 public void afterCommit() {
5     // 事務提交完畢時,觸發:funcB
6     funB();
7 }

 

三、原理

提交一個事務同步處理,在事務commit之後執行,具體存放在threadLocal(線程本地變量)中,事務commit時會去threadLocal裏邊取。源碼afterCommit是空的,沒有任何操作,可見是spring專門預留給大家使用的。

源碼:

TransactionSynchronizationAdapter是一個接口適配器,這樣不用實現接口的全部方法,按需Override即可。類圖如下圖所示:

TransactionSynchronizationAdapter實現了2個接口:

  • TransactionSynchronization事務同步接口,
  • Ordered執行優先級

我們這裏就是實現了TransactionSynchronization接口的afterCommit()方法,最終在事務commit提交後執行。
關於spring事務執行過程圖:

 

四、總結

遇到問題後,很快就想到了處理方式,因爲我提前儲備了相關知識

1.spring事務系列(具體在第三章 事務源碼,裏邊有鏈接)

spring事務詳解(一)初探事務

2.@Async實現異步

異步任務spring @Async註解源碼解析

3.threadLocal線程本地變量

ThreadLocal終極源碼剖析-一篇足矣!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章