如果想在spring操作事務(wù)結(jié)束后執(zhí)行一些代碼,應(yīng)該怎么辦? 為什么要這樣?比如我們?cè)谑聞?wù)中給其他系統(tǒng)發(fā)了消息,期望事務(wù)提交后過一會(huì)收到這個(gè)系統(tǒng)的回應(yīng),然后操作剛剛提交的數(shù)據(jù)。但是如果回應(yīng)來的太快就像龍卷風(fēng),我們的事務(wù)是托管給Spring的可能還沒提交,也就沒法操作了 一個(gè)方案是使用 Applica
在Spring中,如果需要在事務(wù)操作結(jié)束后執(zhí)行一些代碼,可以采取哪些方法呢?
為什么需要這樣做呢?比如,在事務(wù)中向其他系統(tǒng)發(fā)送消息,希望在事務(wù)提交后一段時(shí)間內(nèi)收到該系統(tǒng)的響應(yīng),然后對(duì)剛剛提交的數(shù)據(jù)進(jìn)行操作。但是如果響應(yīng)太快,就像龍卷風(fēng)一樣,我們的事務(wù)可能還沒有提交,這樣就無法進(jìn)行操作。
一種解決方案是使用
ApplicationEventPublisher
,可以參考之前的博客:
https://www.iteye.com/blog/somefuture-2405963
博客訪問量超過100萬,我們假設(shè)總訪問量是10倍哈哈
這個(gè)API是Spring 1就提供的。從Spring 5開始,提供了一個(gè)新的事務(wù)相關(guān)的API,叫
TransactionSynchronization
事務(wù)同步機(jī)制。
首先編寫一個(gè)Bean實(shí)現(xiàn)
TransactionSynchronization
接口
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.stereotype.Component;
@Component
public class AfterTransactionCommitExecutor implements TransactionSynchronization {
@Override
public void afterCommit() {
// 事務(wù)提交后執(zhí)行的操作
System.out.println("事務(wù)已提交,執(zhí)行后續(xù)操作");
}
// 其他需要重寫的方法...
public void registerSynchronization() {
// 注冊(cè)當(dāng)前實(shí)例到事務(wù)同步管理器
TransactionSynchronizationManager.registerSynchronization(this);
}
}
然后,在服務(wù)層或者合適的地方調(diào)用
registerSynchronization()
方法來注冊(cè)事務(wù)同步回調(diào)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SomeService {
@Autowired
private AfterTransactionCommitExecutor afterTransactionCommitExecutor;
@Transactional
public void doWork() {
// 業(yè)務(wù)邏輯...
// 注冊(cè)事務(wù)同步回調(diào)
afterTransactionCommitExecutor.registerSynchronization();
}
}
基本上使用它還是為了操作數(shù)據(jù),所以需要把參數(shù)傳給他。
最簡(jiǎn)單的方法是添加一個(gè)成員屬性。
@Component
public class AfterTransactionCommitExecutor extends TransactionSynchronizationAdapter {
private Object parameter;
@Override
public void afterCommit() {
// 事務(wù)提交后使用參數(shù)執(zhí)行操作
doSomethingWithParameter(parameter);
}
public void setParameter(Object parameter) {
this.parameter = parameter;
}
private void doSomethingWithParameter(Object parameter) {
}
public void registerSynchronization() {
TransactionSynchronizationManager.registerSynchronization(this);
}
}
@Service
public class SomeService {
@Autowired
private AfterTransactionCommitExecutor afterTransactionCommitExecutor;
@Transactional
public void doWork(Object parameter) {
// 設(shè)置參數(shù)
afterTransactionCommitExecutor.setParameter(parameter);
// 注冊(cè)事務(wù)同步回調(diào)
afterTransactionCommitExecutor.registerSynchronization();
}
}
@Service
public class SomeService {
@Transactional
public void doWork(final Object parameter) {
// 業(yè)務(wù)邏輯...
// 注冊(cè)事務(wù)同步回調(diào)并傳遞參數(shù)
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
doSomethingWithParameter(parameter);
}
});
}
private void doSomethingWithParameter(Object parameter) {
// 使用參數(shù)執(zhí)行相關(guān)操作
}
}
需要注意的是,使用成員變量傳遞參數(shù)時(shí),如果多個(gè)事務(wù)并發(fā)執(zhí)行,可能會(huì)存在線程安全問題。為了避免這個(gè)問題,可以使用ThreadLocal來存儲(chǔ)參數(shù),或者在事務(wù)方法中每次都創(chuàng)建一個(gè)新的TransactionSynchronization實(shí)例。
小編推薦閱讀count(*)、count(1)哪個(gè)更快?面試必問:通宵整理的十道經(jīng)典MySQL必問面試題
閱讀從需求分析、產(chǎn)品設(shè)計(jì)到部署交付各階段說明
閱讀如何利用七牛云進(jìn)行數(shù)據(jù)備份和刪除
閱讀強(qiáng)化學(xué)習(xí)筆記之【ACE:Off-PolicyActor-CriticwithCausality-AwareEntropyRegularization】
閱讀使用MailKit在.NET Core中收發(fā)郵件的完整示例
閱讀WiFi基礎(chǔ)(六):天線基礎(chǔ)知識(shí)
閱讀OpenAI官方開源多智能體框架Swarm,社區(qū)反響熱烈
閱讀Vue-Vben-Admin:功能強(qiáng)大的Vue3后臺(tái)管理系統(tǒng)模板
閱讀深度解析Spring AI:請(qǐng)求與響應(yīng)機(jī)制的核心邏輯
閱讀.NET云原生應(yīng)用實(shí)踐(一):從搭建項(xiàng)目框架結(jié)構(gòu)開始
閱讀llama.cpp:一個(gè)適用于中小型研發(fā)企業(yè)的高性能CPU/GPU大語言模型推理框架
閱讀Windows應(yīng)急響應(yīng)-Auto病毒
閱讀本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]
湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2024 haote.com 好特網(wǎng)