spring transaction源碼分析--事務架構


1. 引言  事務特性

事務是並發控制的單元,是用戶定義的一個操作序列。這些操作要么都做,要么都不做,是一個不可分割的工作單位。通過事務將邏輯相關的一組操作綁定在一起,以便服務器 保持數據的完整性。事務通常是以begin transaction開始,以commit或rollback結束。Commint表示提交,即提交事務的所有操作。具體地說就是將事務中所有對數據的更新寫回到磁盤上的物理數據庫中去,事務正常結束。Rollback表示回滾,即在事務運行的過程中發生了某種故障,事務不能繼續進行,系統將事務中對數據庫的所有已完成的操作全部撤消,滾回到事務開始的狀態。

  原子性(Atomic) 對數據的修改要么全部執行,要么全部不執行。

  一致性(Consistent) 在事務執行前后,數據狀態保持一致性。

  隔離性(Isolated) 一個事務的處理不能影響另一個事務的處理。

  持續性(Durable) 事務處理結束,其效果在數據庫中持久化。

 2. Java事務的類型

    Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。

    1、JDBC事務

    JDBC 事務是用 Connection 對象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務模式:自動提交和手工提交。 java.sql.Connection 提供了以下控制事務的方法:

  public void setAutoCommit(boolean)
  public boolean getAutoCommit()
  public void commit()
  public void rollback()


    使用 JDBC 事務界定時,您可以將多個 SQL 語句結合到一個事務中。JDBC 事務的一個缺點是事務的范圍局限於一個數據庫連接。一個 JDBC 事務不能跨越多個數據庫。

 

    2、JTA(Java Transaction API)事務

    JTA是一種高層的,與實現無關的,與協議無關的API,應用程序和應用服務器可以使用JTA來訪問事務。

    JTA允許應用程序執行分布式事務處理——在兩個或多個網絡計算機資源上訪問並且更新數據,這些數據可以分布在多個數據庫上。JDBC驅動程序的JTA支持極大地增強了數據訪問能力。

    如果計划用 JTA 界定事務,那么就需要有一個實現 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅動程序。一個實現了這些接口的驅動程序將可以參與 JTA 事務。一個 XADataSource 對象就是一個 XAConnection 對象的工廠。 XAConnection s 是參與 JTA 事務的 JDBC 連接。

    您將需要用應用服務器的管理工具設置 XADataSource .從應用服務器和 JDBC 驅動程序的文檔中可以了解到相關的指導。

     J2EE應用程序用 JNDI 查詢數據源。一旦應用程序找到了數據源對象,它就調用 javax.sql.DataSource.getConnection() 以獲得到數據庫的連接。

    XA 連接與非 XA 連接不同。一定要記住 XA 連接參與了 JTA 事務。這意味着 XA 連接不支持 JDBC 的自動提交功能。同時,應用程序一定不要對 XA 連接調用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() .

    相反,應用程序應該使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() .

 

    3、容器事務

    容器事務主要是J2EE應用服務器提供的,容器事務大多是基於JTA完成,這是一個基於JNDI的,相當復雜的API實現。相對編碼實現JTA事務管理, 我們可以通過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用服務器提供。這使得我們可以簡單的指定將哪個方法加入事 務,一旦指定,容器將負責事務管理任務。這是我們土建的解決方式,因為通過這種方式我們可以將事務代碼排除在邏輯編碼之外,同時將所有困難交給J2EE容 器去解決。使用EJB CMT的另外一個好處就是程序員無需關心JTA API的編碼,不過,理論上我們必須使用EJB.

    4、三種Java事務差異

      JDBC事務控制的局限性在一個數據庫連接內,但是其使用簡單。

      JTA事務的功能強大,事務可以跨越多個數據庫或多個DAO,使用也比較復雜。

      容器事務,主要指的是J2EE應用服務器提供的事務管理,局限於EJB應用使用。

    5、應用場景

    Java事務控制是構建J2EE應用不可缺少的一部分,合理選擇應用何種事務對整個應用系統來說至關重要。一般說來,在單個JDBC 連接連接的情況下可以選擇JDBC事務,在跨多個連接或者數據庫情況下,需要選擇使用JTA事務,如果用到了EJB,則可以考慮使用EJB容器事務 

 
3. spring事務實現源碼分析

 3.1 dao模塊
    
dao模塊定義了數據庫層的各種異常,其中異常的結構已經在spring-jdbc模塊中介紹過了,在這里主要是dao的支持和異常的轉譯,其數據庫支持和轉譯結構如下所示:

dao 支持
提供了對hibernate、jdbc,cci的支持。我們都想到熟悉,對cci可能有些陌生,下面的章節會講到。
dao異常轉譯
PersistenceExceptionTranslationPostProcessor:自動將標示為@repository的bean的持久化異常進行轉譯。它增加一個PersistenceExceptionTranslationAdvisor來代理相應的已經存在的aop代理或者實現了目標接口的新產生的代理。它將本地資源異常轉換為spring的DataAccessException及其子類上。

PersistenceExceptionTranslationAdvisor是一個spring aop的異常轉譯類,它應用到respository層或者dao層。它基於給定的PersistenceExceptionTranslator來將本地持久化異常轉換為spring的DataAccessException族。

 PersistenceExceptionTranslationInterceptor:一個aop 方法攔截器(MethodInterceptor).提供基於PersistenceExceptionTranslator的異常轉換,它是PersistenceExceptionTranslator的代理,將運行時拋出的異常轉換為spring 的DataAccessException族。

PersistenceExceptionTranslator spring集成其它數據獲取技術(如jpa、toplink、jdo、hibernate等)拋出運行時異常的接口。

3.2 jca模塊
   1. cci模塊



J2EE提供JCA(Java Connector Architecture)規范來標准化對EIS(Enterprise Information System)的訪問。這個規范被分為幾個不同的部分: 

  SPI(Service provider interfaces)是連接器提供者(connector provider)必須實現的接口。 這些接口組成了一個能被部署在J2EE應用服務器上的資源適配器(resource adapter)。 在這種情況下,由服務器來管理連接池(connection pooling)、事務和安全(托管模式(managed mode))。 應用服務器還負責管理客戶端應用程序之外所擁有的配置。連接器(connector)同樣能在脫離應用服務器的情況下使用;在這種情況下,應用程序必須直接對它進行配置(非托管模式(non-managed mode))。 

  CCI (Common Client Interface)是應用程序用來與連接器交互並與EIS通信的接口。同樣還為本地事務划界提供了API。 

  Spring對CCI的支持,目的是為了提供以典型的Spring方式來訪問CCI連接器的類,並有效地使用Spring的通用資源和事務管理工具。 

注意: 
連接器的客戶端不必總是使用CCI。 某些連接器暴露它們自己的API,只提供JCA資源適配器(resource adapter) 以使用J2EE容器的某些系統契約(system contracts)(連接池(connection pooling),全局事務(global transactions),安全(security))。 Spring並沒有為這類連接器特有(connector-specific)的API提供特殊的支持。
 2. context模塊
ResourceAdapterApplicationContext:一個jca ResourceAdapter的applicationContext實現,需要於jca的bootstrapContext一同初始化,最后傳遞到實現了BootstrapContextAware的spring 受管理bean。
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.addBeanPostProcessor(new BootstrapContextAwareProcessor(this.bootstrapContext));
        beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);
        beanFactory.registerResolvableDependency(BootstrapContext.class, this.bootstrapContext);

        // JCA WorkManager resolved lazily - may not be available.
        beanFactory.registerResolvableDependency(WorkManager.class, new ObjectFactory<WorkManager>() {
            @Override
            public WorkManager getObject() {
                return bootstrapContext.getWorkManager();
            }
        });
    }
BootstrapContextAwareProcessor:傳遞BootstrapContext到實現了BootStrapContextAware接口的spring bean。它在內部bean factory中自動注冊。
BootstrapContextAware:需要通知BootStrapContext的實現類。
BootstrapContext:提供一種機制,這種機制將一個Bootstrap的上下文傳遞到一個資源適配器實例。
3.endpoint模塊
AbstractMessageEndpointFactory:實現了jca 1.5、1.6、1.7版本的javax.resource.spi.endpoint.MessageEndpointFactory接口,它提供了事務管理能力。
GenericMessageEndpointFactory實現了抽象方法,對任意類型的消息監聽對象(javax.jms.MessageListener)或者javax.resource.cci.MessageListener對象提供了事務管理的能力。
GenericMessageEndpointManager管理類,對上述方法進行管理。
4.support模塊
LocalConnectionFactoryBean:創建一個本地JCA連接工廠。
ResourceAdapterFactoryBean :使用BootStrapContext啟動一個jca 1.5指定的ResouceAdapter。
5. work模塊
結構如下:

WorkManager提供了提交Work(Work繼承了Runnable)可執行實例的便利類。
3.3 transaction模塊

spring事務架構

3.3.1 事務管理PlatformTransactionManager的架構

如下圖所示:

PlatformTransactionManager:spring事務的核心接口。 

 

 

 

3.3.2 事務定義TransactionDefinition的架構

如下圖所示:

TransactionDefinition:定義spring容器事務屬性的接口。

包括事務傳播行為類型和事務隔離級別:

事務傳播行為類型

事務傳播行為類型

說明

PROPAGATION_REQUIRED

如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。

PROPAGATION_SUPPORTS

支持當前事務,如果當前沒有事務,就以非事務方式執行。

PROPAGATION_MANDATORY

使用當前的事務,如果當前沒有事務,就拋出異常。

PROPAGATION_REQUIRES_NEW

新建事務,如果當前存在事務,把當前事務掛起。

PROPAGATION_NOT_SUPPORTED

以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

PROPAGATION_NEVER

以非事務方式執行,如果當前存在事務,則拋出異常。

PROPAGATION_NESTED

如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

當使用PROPAGATION_NESTED時,底層的數據源必須基於JDBC 3.0,並且實現者需要支持保存點事務機制。

隔離級別:

為了避免上面出現幾種情況在標准SQL規范中定義了4個事務隔離級別,不同隔離級別對事務處理不同

  1. 未授權讀取(Read Uncommitted):也稱未提交讀。防止更新丟失(這不對應一級鎖嗎),如果一個事務已經開始寫數據則另外一個數據則不允許同時進行寫操作但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。事務隔離的最低級別,僅可保證不讀取物理損壞的數據。與READ COMMITTED 隔離級相反,它允許讀取已經被其它用戶修改但尚未提交確定的數據。

  2. 授權讀取(Read Committed):也稱提交讀。1之上防止臟讀取(這不對應二級鎖嗎)。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現,讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交寫事務將會禁止其他事務訪問該行。SQL Server 默認的級別。在此隔離級下,SELECT 命令不會返回尚未提交(Committed) 的數據,也不能返回臟數據。

  3. 可重復讀取(Repeatable Read):2之上防止不可重復讀取(這不對應三級鎖嗎)。但是有時可能出現幻影數據,這可以通過“共享讀鎖”和“排他寫鎖”實現,讀取數據事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。在此隔離級下,用SELECT 命令讀取的數據在整個命令執行過程中不會被更改。此選項會影響系統的效能,非必要情況最好不用此隔離級。

  三級封鎖協議並不能阻止幻讀,修改的不能再被讀取,但是新增(刪除)的記錄數可以統計。

  4. 串行(Serializable):也稱可串行讀(這不對應兩段鎖嗎)。提供嚴格的事務隔離,它要求事務序列化執行,事務只能一個接着一個地執行,但不能並發執行。如果僅僅通過 “行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作事務訪問到。事務隔離的最高級別,事務之間完全隔離。如果事務在可串行讀隔離級別上運行,則可以保證任何並發重疊事務均是串行的。

  LU丟失更新 DR臟讀 NRR非重復讀SLU二類丟失更新 PR幻像讀

為了解決與“多個線程請求相同數據”相關的問題,事務之間用鎖相互隔開。多數主流的數據庫支持不同類型的鎖;因此,JDBC API 支持不同類型的事務,它們由 Connection 對象指派或確定。 
        為了在性能與一致性之間尋求平衡才出現了上面的幾種級別。事務保護的級別越高,性能損失就越大。
        假定您的數據庫和 JDBC 驅動程序支持這個特性,則給定一個 Connection 對象,您可以明確地設置想要的事務級別:
        conn.setTransactionLevel(TRANSACTION_SERIALIZABLE) ;
        可以通過下面的方法確定當前事務的級別:
            int level = conn.getTransactionIsolation();

SavepointManager:管理事務savepoint的編程式API接口。

JDBC定義了SavePoint接口,提供在一個更細粒度的事務控制機制。當設置了一個保存點后,可以rollback到該保存點處的狀態,而不是rollback整個事務。Connection接口的setSavepoint和releaseSavepoint方法可以設置和釋放保存點。

 

 

TransactionStatus:事務狀態表現形式。

 3.3.3 spring事務實現機制

   1 高層

     比較好的方式有:1.基於持久層api的模板方法;2.使用具有事務工廠bean的本地ORM api;3使用代理管理本地資源工廠。

   2 底層

      DataSourceUtils (用作JDBC事務), EntityManagerFactoryUtils (用作JPA事務), SessionFactoryUtils (用作Hibernate事務),PersistenceManagerFactoryUtils (用作JDO事務)等等,

    例如:在使用jdbc時,你可以不通過DataSource的getConnection()方法獲取connection,而是使用以下方法獲取:

  Connection conn = DataSourceUtils.getConnection(dataSource);
3 最低層
TransactionAwareDataSourceProxy是事務的最底層,它代理了DataSource,並增加了spring管理事務功能。
參考資料:
1.http://www.educity.cn/rk/457230.html
2. http://uule.iteye.com/blog/1445678
3. http://zhxing.iteye.com/blog/368110


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM