如果想在spring操作事務結束后執(zhí)行一些代碼,應該怎么辦? 為什么要這樣?比如我們在事務中給其他系統(tǒng)發(fā)了消息,期望事務提交后過一會收到這個系統(tǒng)的回應,然后操作剛剛提交的數(shù)據(jù)。但是如果回應來的太快就像龍卷風,我們的事務是托管給Spring的可能還沒提交,也就沒法操作了 一個方案是使用 Applica
在Spring中,如果需要在事務操作結束后執(zhí)行一些代碼,可以采取哪些方法呢?
為什么需要這樣做呢?比如,在事務中向其他系統(tǒng)發(fā)送消息,希望在事務提交后一段時間內收到該系統(tǒng)的響應,然后對剛剛提交的數(shù)據(jù)進行操作。但是如果響應太快,就像龍卷風一樣,我們的事務可能還沒有提交,這樣就無法進行操作。
一種解決方案是使用
ApplicationEventPublisher
,可以參考之前的博客:
https://www.iteye.com/blog/somefuture-2405963
博客訪問量超過100萬,我們假設總訪問量是10倍哈哈
這個API是Spring 1就提供的。從Spring 5開始,提供了一個新的事務相關的API,叫
TransactionSynchronization
事務同步機制。
首先編寫一個Bean實現(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() {
// 事務提交后執(zhí)行的操作
System.out.println("事務已提交,執(zhí)行后續(xù)操作");
}
// 其他需要重寫的方法...
public void registerSynchronization() {
// 注冊當前實例到事務同步管理器
TransactionSynchronizationManager.registerSynchronization(this);
}
}
然后,在服務層或者合適的地方調用
registerSynchronization()
方法來注冊事務同步回調
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è)務邏輯...
// 注冊事務同步回調
afterTransactionCommitExecutor.registerSynchronization();
}
}
基本上使用它還是為了操作數(shù)據(jù),所以需要把參數(shù)傳給他。
最簡單的方法是添加一個成員屬性。
@Component
public class AfterTransactionCommitExecutor extends TransactionSynchronizationAdapter {
private Object parameter;
@Override
public void afterCommit() {
// 事務提交后使用參數(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ù)
afterTransactionCommitExecutor.setParameter(parameter);
// 注冊事務同步回調
afterTransactionCommitExecutor.registerSynchronization();
}
}
@Service
public class SomeService {
@Transactional
public void doWork(final Object parameter) {
// 業(yè)務邏輯...
// 注冊事務同步回調并傳遞參數(shù)
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
doSomethingWithParameter(parameter);
}
});
}
private void doSomethingWithParameter(Object parameter) {
// 使用參數(shù)執(zhí)行相關操作
}
}
需要注意的是,使用成員變量傳遞參數(shù)時,如果多個事務并發(fā)執(zhí)行,可能會存在線程安全問題。為了避免這個問題,可以使用ThreadLocal來存儲參數(shù),或者在事務方法中每次都創(chuàng)建一個新的TransactionSynchronization實例。
小編推薦閱讀如何使用 Pytorch 中的 DataSet 和 DataLoader
閱讀國產操作系統(tǒng)上實現(xiàn)RTMP推流攝像頭視頻和麥克風聲音到流媒體服務器
閱讀多租戶系統(tǒng)數(shù)據(jù)權限設計與RuoYi系統(tǒng)的借鑒
閱讀count(*)、count(1)哪個更快?面試必問:通宵整理的十道經典MySQL必問面試題
閱讀強化學習筆記之【ACE:Off-PolicyActor-CriticwithCausality-AwareEntropyRegularization】
閱讀使用MailKit在.NET Core中收發(fā)郵件的完整示例
閱讀