?一、PlatformTransactionManager
? ? ? ?1、架構(gòu)設(shè)計理念讓事務(wù)的關(guān)注點與數(shù)據(jù)訪問關(guān)注點分離
? ? ? ?2、PlatformTransactionManager是該架構(gòu)的核心接口,為應(yīng)用程序提供事務(wù)界定的統(tǒng)一方式

? ? ? ? 3、PlatformTransactionManager負責界定事務(wù)邊界,TransactionDefinition負責定義事務(wù)屬性(隔離級別、傳播行為),PlatformTransactionManager將參照TransactionDefinition的屬性定義來開啟相關(guān)事務(wù)。事務(wù)開啟之后到事務(wù)結(jié)束期間的事務(wù)狀態(tài)由TransactionStatus負責,我們也可以通過TransactionStatus對事務(wù)進行有限的控制?!?/p>
類圖

1、Spring的事務(wù)抽象框架以PlatformTransactionManager作為頂層抽象接口,具體的實現(xiàn)交給不同的實現(xiàn)類,使用對象可以根據(jù)當前場景,選擇使用或者替換哪一個具體的實現(xiàn)類。從這個層次看,整個框架的設(shè)計是以Strategy模式為基礎(chǔ)的。不過,從各個實現(xiàn)類的繼承層次上來看,Spring 事務(wù)框架的實現(xiàn)則更多地依賴于模板方法模式。
2、org.springframework.transaction.support.AbstractPlatformTransactionManager作為DataSourceTransactionManager的父類,以模板方法的形式封裝了固定的事務(wù)處理邏輯,而只將與事務(wù)資源相關(guān)的操作以protected或者abstract方法的形式留給DataSourceTransactionManager 來實現(xiàn)。作為模板方法父類,AbstractPlatformTransactionManager替各子類實現(xiàn)了以下固定的?N 務(wù)內(nèi)部處理邏輯:
□判定是否存在當前事務(wù),然后根據(jù)判斷結(jié)果執(zhí)行不同的處理邏輯;
□結(jié)合是否存在當前事務(wù)的情況,根據(jù)TransactionDefinition中指定的傳播行為的不同語義執(zhí)行后繼邏輯;
□根據(jù)情況掛起或者恢復事務(wù);
□提交事務(wù)之前檢查readonly字段是否被設(shè)置,如果是的話,以事務(wù)的回滾代替事務(wù)的提交;
□在事務(wù)回滾的情況下,清理并恢復事務(wù)狀態(tài):
□如果事務(wù)的Synchonization處于active狀態(tài),在事務(wù)處理的規(guī)定時點觸發(fā)注冊的Synchonization 回調(diào)接口。
這些固定的事務(wù)內(nèi)部處理邏輯大都體現(xiàn)在以下幾個主要的模板方法中:
□ public final Transactionstatus getTrcinsaction(TransactionDefinitiondefinition) throws TransactionException
□ public final void rollback(Transactionstatus status) throws TransactionException
□ public final void commit(Transactionstatus status) throws TransactionException
□?protected final SuspendedResourcesHolder suspend(0bject transaction) throws TransactionException
□?protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException
下面詳細介紹幾個模板方法:
2.1、getTransaction(TransactionDefinition)開始。getTransaction (TransactionDefinition)的主要目的是開啟一個事務(wù),但需要在此之前判斷一下之前是否存在一個事務(wù)。如果存在,則根據(jù)TransactionDefinition中的傳播行為決定是掛起當前事務(wù)還是拋出異常。同樣的,不存在事務(wù)的情況下,也需要根據(jù)傳播行為的具體語義來決定如何處理。

1)獲取transaction object,以判斷是否存在當前事務(wù)。
以上這行代碼有如下兩點需要申明。
□ 獲取的transaction object類型會因具體實現(xiàn)類的不同而各異,DataSourceTransactionManager 會返回DataSourceTransactionManager. DataSourceTransacCionObject 類型實例,HibernateTransactionManager會返回HibernateTransactionManager.HibernateTransactionObject類型的實例,等等。AbstractPlatformTransactionManager不需要知道具體實現(xiàn)類返回的transaction object具體類型是什么,因為最終對transaction object的依賴都將通過方法參數(shù)進行傳遞,只要具體的實現(xiàn)類在取得transaction object參數(shù)后知道如何轉(zhuǎn)型就行,所以,這一步返回的transact ion為Object類型。
□ doGetTransaction()是getTransaction(TransactionDefinition)模板方法公開給子類來實現(xiàn)的abstract 類型方法。DataSourceTransactionManager 在實現(xiàn)doGetTransaction ()方法邏輯的時候,會從TransactionSynchronizationManager獲取綁定的資源,然后添加到DataSourceTransactionObject之后返回。
2)檢驗TransactionDefinition參數(shù)合法性。如以下代碼所示:
if (definition == null)(
? ??????definition = new DefaultTransactionDefinition;
)
如果definition參數(shù)為空,則創(chuàng)建一個DefaultTransactionDefinition實例以提供默認的事務(wù)定義數(shù)據(jù)。
3)根據(jù)先前獲得的transaction object判斷是否存在當前事務(wù),根據(jù)判定結(jié)果采取不同的處理方式。

默認情況下,isExistingTransaction(transaction)返回false,該方法需要具體子類根據(jù)情況進行覆寫。對于DataSourceTransactionManager來說,它會根據(jù)傳入的transaction所記載的信息進行判斷,如下所示:

(a)如果isExistingTransaction(transaction)方法返回true,即存在當前事務(wù)的情況下,由handleExistingTransaction ()方法統(tǒng)處理存在當前事務(wù),應(yīng)該如何創(chuàng)建事務(wù)對應(yīng)的Transactionstatus 實例并返回。
如果definition定義的傳播行為是PROPAGATI0N_NEVER,拋出異常并退出.如下:

如果definition定義的傳播行為是PROPAGATION_NOT_SUPPORTED,則掛起當前事務(wù),然后返回. 如下:

newTransactionStatus()方法返回一個DefaultTransactionStatus實例,因為我們掛起了當前事務(wù)。而PROPAGATION_NOT_SUPPORTED不需要事務(wù),所以,返回的DefaultTransactionStatus 不包含transaction object的信息(構(gòu)造方法第二個參數(shù))。
如果definition定義的傳播行為是PROPAGATION-REQUIRES_NEW,則同樣掛起當前事務(wù),并開始—個新的事務(wù)并返回.如下:

AbstractPlatformTransactionManager首先將當前事務(wù)掛起,然后調(diào)用doBegin()方法開始新的事務(wù)。如果開始事務(wù)過程中出現(xiàn)異常,那么恢復之前掛起的事務(wù)。doBegin(transaction, definition)方法為abstract方法,需要具體子類來實現(xiàn)。在DataSourceTransactionManager的doBegin()方法會首先檢查傳入的transaction以提取必要信息判斷之前是否存在綁定的connection信息。如果沒有,則從DataSource中獲取新的connection,然后將其AutoCoiranit狀態(tài)改為false,并綁定到TransactionSynchronizationManager。當然,這期間也會涉及事務(wù)定義的應(yīng)用以及條件檢查等邏輯。在所有一切搞定之后,newTransactionStatus會創(chuàng)建一個包含definition、transaction object以及掛起的事務(wù)信息和其他狀態(tài)信息的DefaultTransactionStatus 實例并返回。
如果definition定義的傳播行為是PROPAGATIONJNESTED,根據(jù)情況創(chuàng)建嵌套事務(wù),如通過Savepoint或者JTA的TransactionManager.如下:

在這種情況下,會首先通過isNestedTransactionAllowed ()方法檢查AbstractPlatform-TransactionManager的nestedTransactionAllowed屬性狀態(tài)。如果允許嵌套事務(wù),那么還得分兩種情況處理。對于DataSourceTransactionManager來說,因為它支持使用Savepoint創(chuàng)建嵌套事務(wù),所以,會使用Transactionstatus創(chuàng)建相應(yīng)的Savepoint并返回。而JtaTransactionManager則要依賴于具體JTA產(chǎn)品的TransactionManager提供嵌套事務(wù)支持。
useSavepointForNestedTransaction()方法默認返回true,即默認使用Savepoint創(chuàng)建嵌套事務(wù)。如果具體子類不支持使用Savepoint創(chuàng)建嵌套事務(wù),則需要覆寫該方法,如JtaTransactionManager。
(b)如果isExistingTransaction (transaction)方法返回false.即不存在當前事務(wù)的情況下。
當definition中定義的傳播行為是PROPAGATION_MANDATORY的時候,拋出異常.因為不存在當 前事務(wù),所以根據(jù)PROPAGATION-MANDATORY的語義,理當如此.
當definition中定義的傳播行為是PROPAGATION_REQUIRED? PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED的時候,開啟新的事務(wù).如下:


之所以在doBegin之前先調(diào)用傳入null的suspend()方法,是因為考慮到如果有注冊Synchronization. 需要暫時將這些與將要開啟的新事務(wù)無關(guān)的Synchronization先放一邊。
剩下的其他情況,則返回不包含任何transaction object的Transactionstatus,這種情況下雖然是空的事務(wù),但有可能需要處理在事務(wù)過程中相關(guān)的Synchronization。
從getTransaction (TransactionDefinition)的邏輯可以看出,AbstractPlat formTran- sactionManager更多關(guān)注的是事務(wù)處理過程中的總體邏輯,而跟具體事務(wù)資源相關(guān)的處理則交給了具體的子類來實現(xiàn)。
2.2? 事務(wù)處理的完成有兩種情況,即回滾事務(wù)或者提交事務(wù),AbstractPlatformTransactionManager提供的rollback (Transactionstatus)和commit (Transactionstatus)兩個模板方法,分別對應(yīng)這兩種情況下的處理。因為事務(wù)提交過程中可能需要處理回滾邏輯,我們不妨以commit (Transactionstatus)的實現(xiàn)流程看一下AbstractPlatformTransactionManager 是如何處理事務(wù)完成的。
(1)因為在事務(wù)處理過程中,我們可以通過Transactionstatus的setRollbackOnly ()方法標記 事務(wù)回滾,所以,commit (Transactionstatus)在具體提交事務(wù)之前會檢查rollBackOnly狀態(tài)。如果該狀態(tài)被設(shè)置,那么轉(zhuǎn)而執(zhí)行事務(wù)的回滾操作。

rollback (Transactionstatus)的邏輯主要包含如下3點。
□回滾事務(wù)。這里的回滾事務(wù)又可分為如下3種情況。
■如果是嵌套事務(wù),則通過Transactionstatus釋放Savepoint。
■如果Transactionstatus表示當前事務(wù)是一個新的事務(wù),則調(diào)用子類的doRollback (Transactionstatus)方法真正的回滾事務(wù)。doRollback(Transactionstatus)是抽象方法,具體子類必須實現(xiàn)它。DataSourceTransactionManager在實現(xiàn)該方法的時候,無疑是調(diào)用connection.rollback()。HibernateTransactionManager會通過它Session上的Transaction 的rollback()方法回滾事務(wù)。其他子類對doRollback (TransactionStatus) 的實現(xiàn)邏輯依此類推。
■如果當前存在事務(wù),并且rollbackOnly狀態(tài)被設(shè)置,則調(diào)用由子類實現(xiàn)的doSet- RollbackOnly (Transactionstatus)方法,各子類實現(xiàn)通常會將當前的transaction object 的狀態(tài)設(shè)置為rollBackOnly。
□觸發(fā)Synchronization 事件。
回滾時觸發(fā)的事件比提交時觸發(fā)的事件要少,只有triggerBeforeCompletion (status)和triggerAfterCompletion。
□清理事務(wù)資源。如下所述。
■設(shè)置Transactionstatus 中的completed 為完成狀態(tài)。
■清理與當前事務(wù)相關(guān)的Synchronization。
■調(diào)用doCleanupAfterCompletion() 放事務(wù)資源,并解除到Transaction SynchronizationManager的資源綁定。對于DataSourceTransactionManager來說,是關(guān)閉數(shù)據(jù)庫連接,然后解除對Datasource對應(yīng)資源的綁定。
■如果之前有掛起的事務(wù),恢復掛起的事務(wù)。
(2)如果rollBackOnly狀態(tài)沒被設(shè)置則執(zhí)行正常的事務(wù)提交操作。
commit (TransactionStatus)方法的其他邏輯與rollback (Transactionstatus)方法基本相似,只是幾個具體操作有所差別,如下所述。
□回滾事務(wù)現(xiàn)在變成是提交事務(wù)。提交事務(wù)的時候,也會涉及如下幾種情況。
■決定是否提前檢測全局的rollBackOnly標志。如果最外層事務(wù)己經(jīng)被標記為rollBackOnly 并且failEarlyOnGlobalRollbackOnly為 true,則拋出異常。
■如果提交事務(wù)之前發(fā)現(xiàn)Transactionstatus持有Savepoint,則釋放它。這實際上是在處理恢套事務(wù)的提交。
■如果Transactionstatus表示要提交的事務(wù)是一個新的事務(wù),則調(diào)用子類的doCoimit (TransactionStatus)方法實現(xiàn)提交事務(wù)。doConunit (Transactionstatus)也是Abstract Plat formTransact ionManager 公開給子類實現(xiàn)的抽象方法,子類必須實現(xiàn)該方法。對于DataSourceTransactionManager來說,因為事務(wù)的提交由Connection決定,所以會直接調(diào)用connection. commit ()提交事務(wù)。其他的子類也會使用自身的局部事務(wù)API在該方法中實現(xiàn)事務(wù)的提交。
□需要觸發(fā)Synchronization相關(guān)事件。不過,觸發(fā)的事件比rolIback (TransactionStatus)中的要多,包括triggerBeforeCoiranit() triggerBeforeCompletion() > triggerAfterCommit ()和triggerAfterCompletion()
□ 如果AbstractplatformTransactionManager 的rollbackOnCommitFailure 狀態(tài)被設(shè)置為true,則表示如果在事務(wù)提交過程中出現(xiàn)異常,需要回滾事務(wù)。所以,當commit (Transactionstatus) 方法捕獲相應(yīng)異常,并且檢測到該字段被設(shè)置的時候,需要回滾事務(wù)。rollbackOnConunitFailure的默認值是false,表示即使提交過程中出現(xiàn)異常,也不回滾事務(wù)。
□既然commit (Transactionstatus)與rolIback(TransactionStatus)~~樣,都是意味著事務(wù)的完成,那么也需要在最后進行事務(wù)資源清理的工作,具體內(nèi)容可以參照rollback (Transactionstatus)