新聞中心
什么是 JTS?

成都創(chuàng)新互聯(lián)公司提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì),品牌網(wǎng)站建設(shè),廣告投放等致力于企業(yè)網(wǎng)站建設(shè)與公司網(wǎng)站制作,10年的網(wǎng)站開發(fā)和建站經(jīng)驗(yàn),助力企業(yè)信息化建設(shè),成功案例突破上千,是您實(shí)現(xiàn)網(wǎng)站建設(shè)的好選擇.
JTS 是一個(gè) 組件事務(wù)監(jiān)視器(component transaction monitor)。這是什么意思?我們將介紹事務(wù)處理監(jiān)視器(TPM)這個(gè)概念,TPM 是一個(gè)程序,它代表應(yīng)用程序協(xié)調(diào)分布式事務(wù)的執(zhí)行。TPM 與數(shù)據(jù)庫(kù)出現(xiàn)的時(shí)間長(zhǎng)短差不多;在 60 年代后期,IBM 首先開發(fā)了 CICS,至今人們?nèi)栽谑褂?。?jīng)典的(或者說 程序化)TPM 管理被程序化定義為針對(duì)事務(wù)性資源(比如數(shù)據(jù)庫(kù))的操作序列的事務(wù)。隨著分布式對(duì)象協(xié)議,如 CORBA、DCOM 和 RMI 的出現(xiàn),人們希望看到事務(wù)更面向?qū)ο蟮那熬?。將事?wù)性語(yǔ)義告知面向?qū)ο蟮慕M件要求對(duì) TPM 模型進(jìn)行擴(kuò)展 ― 在這個(gè)模型中事務(wù)是按照事務(wù)性對(duì)象的調(diào)用方法定義的。JTS 只是一個(gè)組件事務(wù)監(jiān)視器(有時(shí)也稱為 對(duì)象事務(wù)監(jiān)視器(object transaction monitor)),或稱為 CTM。
JTS 和 J2EE 的事務(wù)支持設(shè)計(jì)受 CORBA 對(duì)象事務(wù)服務(wù)(CORBA Object Transaction Service,OTS)的影響很大。實(shí)際上,JTS 實(shí)現(xiàn) OTS 并充當(dāng) Java 事務(wù) API(Java Transaction API)― 一種用來定義事務(wù)邊界的低級(jí) API ― 和 OTS 之間的接口。使用 OTS 代替創(chuàng)建一個(gè)新對(duì)象事務(wù)協(xié)議遵循了現(xiàn)有標(biāo)準(zhǔn),并使 J2EE 和 CORBA 能夠互相兼容。
乍一看,從程序化事務(wù)監(jiān)視器到 CTM 的轉(zhuǎn)變好像只是術(shù)語(yǔ)名稱改變了一下。然而,差別不止這一點(diǎn)。當(dāng) CTM 中的事務(wù)提交或回滾時(shí),與事務(wù)相關(guān)的對(duì)象所做的全部更改都一起被提交或取消。但 CTM 怎么知道對(duì)象在事務(wù)期間做了什么事?象 EJB 組件之類的事務(wù)性組件并沒有 commit() 或 rollback() 方法,它們也沒向事務(wù)監(jiān)視器注冊(cè)自己做了什么事。那么 J2EE 組件執(zhí)行的操作如何變成事務(wù)的一部分呢?
透明的資源征用
當(dāng)應(yīng)用程序狀態(tài)被組件操縱時(shí),它仍然存儲(chǔ)在事務(wù)性資源管理器(例如,數(shù)據(jù)庫(kù)和消息隊(duì)列服務(wù)器)中,這些事務(wù)性資源管理器可以注冊(cè)為分布式事務(wù)中的資源管理器。在第 1 部分中,我們討論了如何在單個(gè)事務(wù)中征用多個(gè)資源管理器,事務(wù)管理器如何協(xié)調(diào)這些資源管理器。資源管理器知道如何把應(yīng)用程序狀態(tài)中的變化與特定的事務(wù)關(guān)聯(lián)起來。
但這只是把問題的焦點(diǎn)從組件轉(zhuǎn)移到了資源管理器 ― 容器如何斷定什么資源與該事務(wù)有關(guān),可以供它征用?請(qǐng)考慮下面的代碼,在典型的 EJB 會(huì)話 bean 中您可能會(huì)發(fā)現(xiàn)這樣的代碼:
清單 1. bean 管理的事務(wù)的透明資源征用
| 1 InitialContext ic = new InitialContext(); 2 UserTransaction ut = ejbContext.getUserTransaction(); 3 ut.begin(); 4 DataSource db1 = (DataSource) ic.lookup("java:comp/env/OrdersDB"); 5 DataSource db2 = (DataSource) ic.lookup("java:comp/env/InventoryDB"); 6 Connection con1 = db1.getConnection(); 7 Connection con2 = db2.getConnection(); 8 // perform updates to OrdersDB using connection con1 9 // perform updates to InventoryDB using connection con2 10 ut.commit(); 11 |
注意,這個(gè)示例中沒有征用當(dāng)前事務(wù)中 JDBC 連接的代碼 ― 容器會(huì)為我們完成這個(gè)任務(wù)。我們來看一下它是如何發(fā)生的。
資源管理器的三種類型
當(dāng)一個(gè) EJB 組件想訪問數(shù)據(jù)庫(kù)、消息隊(duì)列服務(wù)器或者其它一些事務(wù)性資源時(shí),它需要到資源管理器的連接(通常是使用 JNDI)。而且,J2EE 規(guī)范只認(rèn)可三種類型的事務(wù)性資源 ― JDBC 數(shù)據(jù)庫(kù)、JMS 消息隊(duì)列服務(wù)器和“其它通過 JCA 訪問的事務(wù)性服務(wù)”。后面一種服務(wù)(比如 ERP 系統(tǒng))必須通過 JCA(J2EE Connector Architecture,J2EE 連接器體系結(jié)構(gòu))訪問。對(duì)于這些類型資源中的每一種,容器或提供者都會(huì)幫我們把資源征調(diào)到事務(wù)中。
在清單 1 中, con1 和 con2 好象是普通的 JDBC 連接,比如那些從 DriverManager.getConnection() 返回的連接。我們從一個(gè) JDBC DataSource 得到這些連接,JDBC DataSource 可以通過查找 JNDI 中的數(shù)據(jù)源名稱得到。EJB 組件中被用來查找數(shù)據(jù)源( java:comp/env/OrdersDB )的名稱是特定于組件的;組件的部署描述符的 resource-ref 部分將其映射為容器管理的一些應(yīng)用程序級(jí) DataSource 的 JNDI 名稱。
隱藏的 JDBC 驅(qū)動(dòng)器
每個(gè) J2EE 容器都可以創(chuàng)建有事務(wù)意識(shí)的池態(tài) DataSource 對(duì)象,但 J2EE 規(guī)范并不向您展示如何創(chuàng)建,因?yàn)檫@不在 J2EE 規(guī)范內(nèi)。瀏覽 J2EE 文檔時(shí),您找不到任何關(guān)于如何創(chuàng)建 JDBC 數(shù)據(jù)源的內(nèi)容。相反,您不得不為您的容器查閱該文檔。創(chuàng)建一個(gè)數(shù)據(jù)源可能需要向?qū)傩曰蚺渲梦募砑右粋€(gè)數(shù)據(jù)源定義,或者也可以通過 GUI 管理工具完成,這取決于您的容器。
每個(gè)容器(或連接池管理器,如 PoolMan)都提供它自己的創(chuàng)建 DataSource 機(jī)制,JTA 魔術(shù)就隱藏在這個(gè)機(jī)制中。連接池管理器從指定的 JDBC 驅(qū)動(dòng)器得到一個(gè) Connection ,但在將它返回到應(yīng)用程序之前,將它與一個(gè)也實(shí)現(xiàn) Connection 的虛包包在一起,將自己置入應(yīng)用程序和底層連接之間。當(dāng)創(chuàng)建連接或者執(zhí)行 JDBC 操作時(shí),包裝器詢問事務(wù)管理器當(dāng)前線程是不是正在事務(wù)的上下文中執(zhí)行,如果事務(wù)中有 Connection 的話,就自動(dòng)征用它。
其它類型的事務(wù)性資源,JMS 消息隊(duì)列和 JCA 連接器,依靠相似的機(jī)制將資源征用隱藏起來,使用戶看不到。如果要使 JMS 隊(duì)列在部署時(shí)對(duì) J2EE 應(yīng)用程序可用,您就要再次使用特定于提供者的機(jī)制來創(chuàng)建受管 JMS 對(duì)象(隊(duì)列連接工廠和目標(biāo)),然后在 JNDI 名稱空間內(nèi)發(fā)布這些對(duì)象。提供者創(chuàng)建的受管對(duì)象包含與 JDBC 包裝器(由容器提供的連接池管理器添加)相似的自動(dòng)征用代碼。
透明的事務(wù)控制
兩種類型的 J2EE 事務(wù) ― 容器管理的和 bean 管理的 ― 在如何啟動(dòng)和結(jié)束事務(wù)上是不同的。事務(wù)啟動(dòng)和結(jié)束的地方被稱為 事務(wù)劃分(transaction demarcation)。清單 1 中的示例代碼演示了 bean 管理的事務(wù)(有時(shí)也稱為 編程(programmatic)事務(wù))。Bean 管理的事務(wù)是由組件使用 UserTransaction 類顯式啟動(dòng)和結(jié)束的。通過 ejbContext 使 UserTransaction 對(duì) EJB 組件可用,通過 JNDI 使其對(duì)其它 J2EE 組件可用。
容器根據(jù)組件的部署描述符中的事務(wù)屬性代表應(yīng)用程序透明地啟動(dòng)和結(jié)束容器管理的事務(wù)(或稱為 宣告式事務(wù)(declarative transaction))。通過將 transaction-type 屬性設(shè)置為 Container 或 Bean 您可以指出 EJB 組件是使用 bean 管理的事務(wù)性支持還是容器管理的事務(wù)性支持。
使用容器管理的事務(wù),您可以在 EJB 類或方法級(jí)別上指定事務(wù)性屬性;您可以為 EJB 類指定缺省的事務(wù)性屬性,如果不同的方法會(huì)有不同的事務(wù)性語(yǔ)義,您還可以為每個(gè)方法指定屬性。這些事務(wù)性屬性在裝配描述符(assembly descriptor)的 container-transaction 部分被指定。清單 2 顯示了一個(gè)裝配描述符示例。 trans-attribute 的受支持的值有:
Supports
Required
RequiresNew
Mandatory
NotSupported
Never
trans-attribute 決定方法是否支持在事務(wù)內(nèi)部執(zhí)行、當(dāng)在事務(wù)內(nèi)部調(diào)用方法時(shí)容器會(huì)執(zhí)行什么操作以及在事務(wù)外部調(diào)用方法時(shí)容器會(huì)執(zhí)行什么操作。最常用的容器管理的事務(wù)屬性是 Required 。如果設(shè)置了 Required ,過程中的事務(wù)將在該事務(wù)中征用您的 bean,但如果沒有正在運(yùn)行的事務(wù),容器將為您啟動(dòng)一個(gè)。在這個(gè)系列的第 3 部分,當(dāng)您可能想使用每個(gè)事務(wù)屬性時(shí),我們將研究各個(gè)事務(wù)屬性之間的區(qū)別。
清單 2. EJB 裝配描述符樣本
| 1 2 ... 3 4 5 6 7 method> 8 9 container-transaction> 10 11 12 13 14 method> 15 16 container-transaction> 17 ... 18 assembly-descriptor> 19 |
功能強(qiáng)大,但很危險(xiǎn)
與清單 1 中的示例不同,由于有宣告式事務(wù)劃分,這段組件代碼中沒有事務(wù)管理代碼。這不僅使結(jié)果組件代碼更加易讀(因?yàn)樗慌c事務(wù)管理代碼混在一起),而且它還有另一個(gè)更重要的優(yōu)點(diǎn) ― 不必修改,甚至不必訪問組件的源代碼,就可以在應(yīng)用程序裝配時(shí)改變組件的事務(wù)性語(yǔ)義。
盡管能夠指定與代碼分開的事務(wù)劃分是一種非常強(qiáng)大的功能,但在裝配時(shí)做出不好的決定會(huì)使應(yīng)用程序變得不穩(wěn)定,或者嚴(yán)重影響它的性能。對(duì)容器管理的事務(wù)進(jìn)行正確分界的責(zé)任由組件開發(fā)者和應(yīng)用程序裝配人員共同擔(dān)當(dāng)。組件開發(fā)者需要提供足夠的文檔說明組件是做什么的,這樣應(yīng)用程序部署者就能夠明智地決定如何構(gòu)建應(yīng)用程序的事務(wù)。應(yīng)用程序裝配人員需要理解應(yīng)用程序中的組件是怎樣相互作用的,這樣就可以用一種既強(qiáng)制應(yīng)用程序保持一致又不削弱性能的方法對(duì)事務(wù)進(jìn)行分界。在這個(gè)系列的第 3 部分中我們將討論這些問題。
透明的事務(wù)傳播
在任何類型的事務(wù)中,資源征用都是透明的;容器自動(dòng)將事務(wù)過程中使用的任意事務(wù)性資源征調(diào)到當(dāng)前事務(wù)中。這個(gè)過程不僅擴(kuò)展到事務(wù)性方法使用的資源(比如在清單 1 中獲得的數(shù)據(jù)庫(kù)連接),還擴(kuò)展到它調(diào)用的方法(甚至遠(yuǎn)程方法)使用的資源。我們來看一下這是如何發(fā)生的。
容器用線程與事務(wù)相關(guān)聯(lián)
我們假設(shè)對(duì)象 A 的 methodA() 啟動(dòng)一個(gè)事務(wù),然后調(diào)用對(duì)象 B 的 methodB() (對(duì)象 B 將得到一個(gè) JDBC 連接并更新數(shù)據(jù)庫(kù))。 B 獲得的連接將被自動(dòng)征調(diào)到 A 創(chuàng)建的事務(wù)中。容器怎么知道要做這件事?
當(dāng)事務(wù)啟動(dòng)時(shí),事務(wù)上下文與執(zhí)行線程關(guān)聯(lián)在一起。當(dāng) A 創(chuàng)建事務(wù)時(shí), A 在其中執(zhí)行的線程與該事務(wù)關(guān)聯(lián)在一起。由于本地方法調(diào)用與主調(diào)程序(caller)在同一個(gè)線程內(nèi)執(zhí)行,所以 A 調(diào)用的每個(gè)方法也都在該事務(wù)的上下文中。
櫥中骸骨
如果對(duì)象 B 其實(shí)是在另一個(gè)線程,甚至另一個(gè) JVM 中執(zhí)行的 EJB 組件的存根,情況會(huì)怎樣?令人吃驚的是,遠(yuǎn)程對(duì)象 B 訪問的資源仍將在當(dāng)前事務(wù)中被征用。EJB 對(duì)象存根(在主調(diào)程序的上下文中執(zhí)行的那部分)、EJB 協(xié)議(IIOP 上的 RMI)和遠(yuǎn)端的骨架對(duì)象協(xié)力要使其透明地發(fā)生。存根確定調(diào)用者是不是正在執(zhí)行一個(gè)事務(wù)。如果是,事務(wù)標(biāo)識(shí),或者說 Xid,被作為 IIOP 調(diào)用的一部分與方法參數(shù)一起傳播到遠(yuǎn)程對(duì)象。(IIOP 是 CORBA 遠(yuǎn)程-調(diào)用協(xié)議,它為傳播執(zhí)行上下文(比如事務(wù)上下文和安全性上下文)的各種元素而備;關(guān)于 RMI over IIOP 的更多信息,請(qǐng)參閱 參考資料。)如果調(diào)用是事務(wù)的一部分,那么遠(yuǎn)程系統(tǒng)上的骨架對(duì)象自動(dòng)設(shè)置遠(yuǎn)程線程的事務(wù)上下文,這樣,當(dāng)調(diào)用實(shí)際的遠(yuǎn)程方法時(shí),它已經(jīng)是事務(wù)的一部分了。(存根和骨架對(duì)象還負(fù)責(zé)開始和提交容器管理的事務(wù)。)
事務(wù)可以由任何 J2EE 組件來啟動(dòng) ― 一個(gè) EJB 組件、一個(gè) servlet 或者一個(gè) JSP 頁(yè)面(如果容器支持的話,還可以是一個(gè)應(yīng)用程序客戶機(jī))。這意味著,應(yīng)用程序可以在請(qǐng)求到達(dá)時(shí)在 servlet 或者 JSP 頁(yè)面中啟動(dòng)事務(wù)、在 servlet 或者 JSP 頁(yè)面中執(zhí)行一些處理、作為頁(yè)面邏輯的一部分訪問多個(gè)服務(wù)器上的實(shí)體 bean 和會(huì)話 bean 并使所有這些工作透明地成為一個(gè)事務(wù)的一部分。圖 1 演示了事務(wù)上下文怎樣遵守從 servlet 到 EJB,再到 EJB 的執(zhí)行路徑。
圖 1.單個(gè)事務(wù)中的多個(gè)組件
最優(yōu)化
讓容器來管理事務(wù)允許容器為我們做出某些最優(yōu)化決定。在圖 1 中,我們看到一個(gè) servlet 和多個(gè) EJB 組件在單個(gè)事務(wù)的上下文中訪問一個(gè)數(shù)據(jù)庫(kù)。每個(gè)組件都獲得到數(shù)據(jù)庫(kù)的 Connection ;很可能每個(gè)組件都在訪問同一個(gè)數(shù)據(jù)庫(kù)。即使多個(gè)連接是從不同的組件到同一個(gè)資源,JTS 也可以檢測(cè)出多個(gè)資源是否和事務(wù)有關(guān),并最優(yōu)化該事務(wù)的執(zhí)行。您可以從第 1 部分回憶起來,單個(gè)事務(wù)要包含多個(gè)資源管理器需要使用兩階段提交協(xié)議,這比單個(gè)資源管理器使用的單階段提交代價(jià)要高。JTS 能夠確定事務(wù)中是不是只征用了一個(gè)資源管理器。如果它檢測(cè)出所有與事務(wù)相關(guān)的資源都一樣,它可以跳過兩階段提交并讓資源管理器自己來處理事務(wù)。
結(jié)束語(yǔ)
這個(gè)慮及透明事務(wù)控制、資源征用和透明傳播的魔術(shù)不是 JTS 的一部分,而是 J2EE 容器如何在幕后代表 J2EE 應(yīng)用程序使用 JTA 和 JTS 服務(wù)的一部分。在幕后有許多實(shí)體合力使這個(gè)魔術(shù)透明地發(fā)生;EJB 存根和骨架、容器廠商提供的 JDBC 驅(qū)動(dòng)器包裝器、數(shù)據(jù)庫(kù)廠商提供的 JDBC 驅(qū)動(dòng)器、JMS 提供器和 JCA 連接器。所有這些實(shí)體都與事務(wù)管理器進(jìn)行交互,于是應(yīng)用程序代碼就不必與之交互了。
本文標(biāo)題:Java理論和實(shí)踐:理解JTS
本文網(wǎng)址:http://fisionsoft.com.cn/article/dhehgdd.html


咨詢
建站咨詢
