Spring中TransactionSynchronizationManager的使用詳解
1 概述
TransactionSynchronizationManager : 事務(wù)同步管理器,監(jiān)聽事務(wù)的操作,來實現(xiàn)在事務(wù)前后可以添加一些指定操作
在遇到一些場景, 如上一步保存的數(shù)據(jù), 在接下來的異步處理的業(yè)務(wù)中有使用,但是因為保存數(shù)據(jù)過程中,可能出現(xiàn)異常,導(dǎo)致數(shù)據(jù)回滾,那么后續(xù)的業(yè)務(wù)操作也需要放棄. 對于上述業(yè)務(wù)場景, 可以使用TransactionSynchronizationManager解決問題
查看一下 TransactionSynchronizationManager 類 :
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
// ...
}參數(shù)說明:
- resources 保存連接資源, 一個方法里面可能包含兩個事務(wù)(比如事務(wù)傳播特性為:TransactionDefinition#PROPAGATION_REQUIRES_NEW),所以就用 Map 來保存資源.
- synchronizations 線程同步器,對 Spring 事務(wù)的擴展. 在Spring中通過@Transactional注解,在方法上,這個方法就有事務(wù)特性.
- currentTransactionReadOnly 保存當前事務(wù)是否只讀
- currentTransactionName 保存當前事務(wù)名稱,默認為空
- currentTransactionIsolationLevel 保存當前事務(wù)的隔離級別
- actualTransactionActive 保存當前事務(wù)是否還處于Active活躍狀態(tài)
2 案例
以常見的用戶注冊,然后發(fā)送激活碼為例.
public void save(){
// 保存用戶
saveUser();
// 發(fā)送消息 異步執(zhí)行
executorService.execute(() -> sendMessage());
}說明:
在用戶注冊操作, 會將用戶信息報錯,可能會調(diào)一些其他模塊,如積分模塊等等, 進行數(shù)據(jù)庫報錯操作.會進行數(shù)據(jù)回滾, 但是異步操作,此時不能再進行回滾了.
所以我們需要等保存數(shù)據(jù)的事務(wù),已經(jīng)完成提交,再執(zhí)行異步操作.
改造:
public void save(){
// 保存用戶
saveUser();
// 判斷當前線程是否存在活躍狀態(tài)的事務(wù)
boolean actualTransactionActive = TransactionSynchronizationManager.isActualTransactionActive();
// 不存在則事務(wù)都完成
if (!actualTransactionActive){
// 異步操作 發(fā)送消息
executorService.execute(() -> sendMessage());
}else{
// 存在活躍事務(wù), 則監(jiān)聽事務(wù), afterCommit是指事務(wù)提交完再執(zhí)行
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 異步操作 發(fā)送消息
executorService.execute(() -> sendMessage());
}
});
}
}通過TransactionSynchronizationManager,保證當前線程的事務(wù)都提交完成后,再進行異步的消息發(fā)送,解決了上述的問題. 避免出現(xiàn)數(shù)據(jù)未保存,而發(fā)送激活碼或提示信息等.
查看一下 TransactionSynchronizationAdapter 類
public abstract class TransactionSynchronizationAdapter implements TransactionSynchronization, Ordered {
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
// 暫停此同步 應(yīng)該從事務(wù)同步管理器中解綁資源
@Override
public void suspend() {
}
// 恢復(fù)此同步。 應(yīng)該將資源重新綁定到 TransactionSynchronizationManager
@Override
public void resume() {
}
// 將基礎(chǔ)會話刷新到數(shù)據(jù)存儲
@Override
public void flush() {
}
// 在事務(wù)提交之前調(diào)用(在完成之前之前)順序倒數(shù)第四
@Override
public void beforeCommit(boolean readOnly) {
}
// 在事務(wù)提交/回滾之前調(diào)用。順序倒數(shù)第三
@Override
public void beforeCompletion() {
}
// 在事務(wù)提交后調(diào)用 順序倒數(shù)第二
@Override
public void afterCommit() {
}
// 在事務(wù)提交/回滾后調(diào)用 可以進行資源清理 順序倒數(shù)第一
@Override
public void afterCompletion(int status) {
}
}根據(jù)上述類方法含義,通常業(yè)務(wù)選擇使用afterCommit進行重寫,執(zhí)行異步業(yè)務(wù)操作.
3 總結(jié)
在上述問題已經(jīng)場景, 之前有遇到過幾次, 都是采用了其他方法解決, 那些方法或多或少都有一些問題,如甚至使用過編程式事務(wù)去進行二次控制.而使用TransactionSynchronizationManager, 則是很符合這個業(yè)務(wù)場景的需求.
到此這篇關(guān)于Spring中TransactionSynchronizationManager的使用詳解的文章就介紹到這了,更多相關(guān)TransactionSynchronizationManager的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Springboot如何優(yōu)雅的進行數(shù)據(jù)校驗
基于?Spring?Boot?,如何“優(yōu)雅”的進行數(shù)據(jù)校驗?zāi)?,本文將待大家詳細介紹Springboot如何優(yōu)雅的進行數(shù)據(jù)校驗,文中有詳細的代碼示例和流程步驟,需要的朋友可以參考下2023-06-06

