需求:在保證事務(wù)提交之后執(zhí)行某些操作剪验。
解決:
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
//do something
}
});
源碼:
/**
* Register a new transaction synchronization for the current thread.
* Typically called by resource management code.
* <p>Note that synchronizations can implement the
* {@link org.springframework.core.Ordered} interface.
* They will be executed in an order according to their order value (if any).
* @param synchronization the synchronization object to register
* @throws IllegalStateException if transaction synchronization is not active
* @see org.springframework.core.Ordered
*/
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchs.add(synchronization);
}
看第一行注釋 Register a new transaction synchronization for the current thread.
為當(dāng)前線程注冊(cè)一個(gè)事務(wù)synchronization ,
注冊(cè)到哪了呢异吻,猜也猜到了韧衣,當(dāng)然是ThreadLocal
啦其弊!
注冊(cè)的是嘛玩意呢巫橄?
從最初的代碼可以看到注冊(cè)是的 TransactionSynchronizationAdapter
(從明明后綴可以知道這個(gè)是適配器接口)
源碼中ThreadLocal中維護(hù)的是一個(gè) TransactionSynchronization
的列表
TransactionSynchronization
定義了beforeCommit慕爬,afterCommit等方法
而TransactionSynchronizationAdapter
正是TransactionSynchronization
的抽象實(shí)現(xiàn)
可以看到都是空實(shí)現(xiàn)窑眯,這樣設(shè)計(jì)的好處是,當(dāng)業(yè)務(wù)需要用到時(shí)医窿,無(wú)需實(shí)現(xiàn)接口全部的方法磅甩, 按需實(shí)現(xiàn)即可。典型的適配器模式姥卢。
講了那么多卷要,看一下事務(wù)提交后是怎么調(diào)用TransactionSynchronization
的呢?独榴?僧叉? 看到這里估計(jì)你心中已有了答案。
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit
//提交事務(wù)的核心邏輯
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
//…… 省略無(wú)關(guān)代碼
//提交事務(wù)
doCommit(status);
//看這里棺榔,處理提交事務(wù)之后的邏輯
triggerAfterCommit(status);
//……省略無(wú)關(guān)代碼
}
private void triggerAfterCommit(DefaultTransactionStatus status) {
TransactionSynchronizationUtils.triggerAfterCommit();
}
//TransactionSynchronizationManager.getSynchronizations()就是獲取所有注冊(cè)的Synchronizations并排個(gè)序啥的
public static void triggerAfterCommit() {
invokeAfterCommit(TransactionSynchronizationManager.getSynchronizations());
}
//最終就在這了
public static void invokeAfterCommit(@Nullable List<TransactionSynchronization> synchronizations) {
if (synchronizations != null) {
for (TransactionSynchronization synchronization : synchronizations) {
synchronization.afterCommit();
}
}
}
總結(jié): 一個(gè)好的框架里有非常多的設(shè)計(jì)思想和code風(fēng)格值的學(xué)習(xí)瓶堕。
當(dāng)前還有一種更為優(yōu)雅的方式(注解+事件驅(qū)動(dòng)
,擺脫硬編碼症歇,減少代碼侵入)捞烟,可以解決類似問(wèn)題。
預(yù)知后事如何当船,且聽下回分解