Spring - Java/J2EE Application Framework 应用框架 第 7 章 事务管理
第?7?章?事務(wù)管理
7.1.?Spring事務(wù)抽象
Spring提供了一致的事務(wù)管理抽象。這個抽象是Spring最重要的抽象之一, 它有如下的優(yōu)點:
-
為不同的事務(wù)API提供一致的編程模型,如JTA、JDBC、Hibernate、iBATIS數(shù)據(jù)庫層 和JDO
-
提供比大多數(shù)事務(wù)API更簡單的,易于使用的編程式事務(wù)管理API
-
整合Spring數(shù)據(jù)訪問抽象
-
支持Spring聲明式事務(wù)管理
傳統(tǒng)上,J2EE開發(fā)者有兩個事務(wù)管理的選擇:?全局事務(wù)或?局部事務(wù)。全局事務(wù)由應(yīng)用服務(wù)器管理,使用JTA。局部 事務(wù)是和資源相關(guān)的:例如,一個和JDBC連接關(guān)聯(lián)的事務(wù)。這個選擇有深刻的含義。 全局事務(wù)可以用于多個事務(wù)性的資源(需要指出的是多數(shù)應(yīng)用使用單一事務(wù)性 的資源)。使用局部事務(wù),應(yīng)用服務(wù)器不需要參與事務(wù)管理,并且不能幫助確保 跨越多個資源的事務(wù)的正確性。
全局事務(wù)有一個顯著的不利方面,代碼需要使用JTA:一個笨重的API(部分是 因為它的異常模型)。此外,JTA的UserTransaction通常需 要從JNDI獲得,這意味著我為了JTA需要同時使用JNDI和JTA。 顯然全部使用全局事務(wù)限制了應(yīng)用代碼的重用性,因為JTA通常只在應(yīng)用服 務(wù)器的環(huán)境中才能使用。
使用全局事務(wù)的比較好的方法是通過EJB的CMT?(容器管理的事務(wù)):?聲明式事務(wù)管理的一種形式(區(qū)別于編程式事務(wù)管理?)。EJB的CMT不需要任何和事務(wù)相關(guān)的JNDI查找,雖然使用EJB本身 肯定需要使用JNDI。它消除大多數(shù)——不是全部——書寫Java代碼控制事務(wù)的需求。 顯著的缺點是CMT綁定在JTA和應(yīng)用服務(wù)器環(huán)境上,并且只有我們選擇 使用EJB實現(xiàn)業(yè)務(wù)邏輯,或者至少處于一個事務(wù)化EJB的外觀(Facade)后 才能使用它。EJB有如此多的詬病,當(dāng)存在其它聲明式事務(wù)管理時, EJB不是一個吸引人的建議。
局部事務(wù)容易使用,但也有明顯的缺點:它們不能用于多個事務(wù)性資 源,并且趨向侵入的編程模型。例如,使用JDBC連接事務(wù)管理的代碼不能用于 全局的JTA事務(wù)中。
Spring解決了這些問題。它使應(yīng)用開發(fā)者能夠使用在任何環(huán)境?下使用一致的編程模型。你可以只寫一次你的代碼,這在不同環(huán)境 下的不同事務(wù)管理策略中很有益處。Spring同時提供聲明式和編程式事務(wù)管理。
使用編程式事務(wù)管理,開發(fā)者直接使用Spring事務(wù)抽象,這個抽象可以使用在任何 底層事務(wù)基礎(chǔ)之上。使用首選的聲明式模型,開發(fā)者通常書寫很少的事務(wù)相關(guān)代 碼,因此不依賴Spring或任何其他事務(wù)API。
7.2.?事務(wù)策略
Spring事務(wù)抽象的關(guān)鍵是事務(wù)策略的概念。
這個概念由?org.springframework.transaction.PlatformTransactionManager?接口體現(xiàn),如下:
public interface PlatformTransactionManager {TransactionStatus getTransaction(TransactionDefinition definition)throws TransactionException;void commit(TransactionStatus status) throws TransactionException;void rollback(TransactionStatus status) throws TransactionException; }這首先是一個SPI接口,雖然它也可以在編碼中使用。注意按照Spring的哲學(xué), 這是一個接口。因而如果需要它可以很容易地被模擬和 樁化。它也沒有和一個查找策略如JNDI捆綁在一起:PlatformTransactionManager 的實現(xiàn)定義和其他Spring IoC容器中的對象一樣。這個好處使得即使使用JTA,也 是一個很有價值的抽象:事務(wù)代碼可以比直接使用JTA更加容易測試。
繼續(xù)Spring哲學(xué),TransactionException是unchecked的。 低層的事務(wù)失敗幾乎都是致命。很少情況下應(yīng)用程序代碼可以從它們 中恢復(fù),不過應(yīng)用開發(fā)者依然可以捕獲并處理?TransactionException。
getTransaction()根據(jù)一個類型為?TransactionDefinition的參數(shù)返回一個?TransactionStatus對象。返回的?TransactionStatus對象可能代表一個新的或已經(jīng)存在的事 務(wù)(如果在當(dāng)前調(diào)用堆棧有一個符合條件的事務(wù))。
如同J2EE事務(wù)上下文一樣,一個TransactionStatus也是和執(zhí) 行的線程關(guān)聯(lián)的。
TransactionDefinition接口指定:
-
事務(wù)隔離:當(dāng)前事務(wù)和其它事務(wù)的隔離的程度。 例如,這個事務(wù)能否看到其他事務(wù)未提交的寫數(shù)據(jù)?
-
事務(wù)傳播:通常在一個事務(wù)中執(zhí)行的 所有代碼都會在這個事務(wù)中運行。但是,如果一個事務(wù)上下文已經(jīng)存在, 有幾個選項可以指定一個事務(wù)性方法的執(zhí)行行為:例如,簡單地在現(xiàn)有的 事務(wù)中運行(大多數(shù)情況);或者掛起現(xiàn)有事務(wù),創(chuàng)建一個新的事務(wù)。 Spring提供EJB CMT中熟悉的事務(wù)傳播選項。
-
事務(wù)超時: 事務(wù)在超時前能運行多 久(自動被底層的事務(wù)基礎(chǔ)設(shè)施回滾)。
-
只讀狀態(tài): 只讀事務(wù)不修改任何數(shù) 據(jù)。只讀事務(wù)在某些情況下(例如當(dāng)使用Hibernate時)可可是一種非常有用的優(yōu)化。
這些設(shè)置反映了標(biāo)準(zhǔn)概念。如果需要,請查閱討論事務(wù)隔離層次和其他核心事 務(wù)概念的資源:理解這些概念在使用Spring和其他事務(wù)管理解決方案時是非常關(guān)鍵的。
TransactionStatus接口為處理事務(wù)的代碼提供一個簡單 的控制事務(wù)執(zhí)行和查詢事務(wù)狀態(tài)的方法。這個概念應(yīng)該是熟悉的,因為它們在所 有的事務(wù)API中是相同的:
public interface TransactionStatus {boolean isNewTransaction();void setRollbackOnly();boolean isRollbackOnly(); }但是使用Spring事務(wù)管理時,定義?PlatformTransactionManager的實現(xiàn)是基本方式。在好的Spring 風(fēng)格中,這個重要定義使用IoC實現(xiàn)。
PlatformTransactionManager實現(xiàn)通常需要了解它們工作 的環(huán)境:JDBC、JTA、Hibernate等等。
下面來自Spring范例jPetstore中的?dataAccessContext-local.xml,它展示了一個局部 PlatformTransactionManager實現(xiàn)是如何定義的。它將和JDBC一起工作。
我們必須定義JDBC數(shù)據(jù)源,然后使用DataSourceTransactionManager,提供給 它的一個數(shù)據(jù)源引用。
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName"><value>${jdbc.driverClassName}</value></property><property name="url"><value>${jdbc.url}</value></property><property name="username"><value>${jdbc.username}</value></property><property name="password"><value>${jdbc.password}</value></property> </bean>PlatformTransactionManager定義如下:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource"><ref local="dataSource"/></property> </bean>如果我們使用JTA,如同范例中dataAccessContext-jta.xml, 我們需要使用通過JNDI獲得的容器數(shù)據(jù)源,和一個JtaTransactionManager實 現(xiàn)。JtaTransactionManager不需要知道數(shù)據(jù)源,或任何其他特定資源,因為它將 使用容器的全局事務(wù)管理。
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"><property name="jndiName"><value>jdbc/jpetstore</value></property> </bean><bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>我們可以很容易地使用Hibernate局部事務(wù),如同下面Spring的PetClinic?示例應(yīng)用中的例子的一樣。
在這種情況下,我們需要定義一個Hibernate的LocalSessionFactory,應(yīng)用程 序?qū)⑹褂盟@得Hibernate的會話。
數(shù)據(jù)源bean定義和上面例子類似,這里不再羅列(如果這是容器數(shù)據(jù)源,它應(yīng)該是非事務(wù)的,因為Spring會管理事務(wù), 而不是容器)。
這種情況下,“transactionManager” bean的類型是HibernateTransactionManager。 和DataSourceTransactionManager擁有一個數(shù)據(jù)源的引用一樣, HibernateTransactionManager需要一個SessionFactory的引用。
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"><property name="dataSource"><ref local="dataSource"/></property><property name="mappingResources"><value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">${hibernate.dialect}</prop></props></property> </bean><bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"><property name="sessionFactory"><ref local="sessionFactory"/></property> </bean>使用Hibernate和JTA事務(wù),我們可以簡單地使用JtaTransactionManager, 就象JDBC或任何其他資源策略一樣。
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>注意任何資源的JTA配置都是這樣的,因為它們都是全局事務(wù)。
在所有這些情況下,應(yīng)用程序代碼不需要任何更改。我們可以僅僅更改配置 來更改管理事務(wù)的方式,即使這些更改意味這從局部事務(wù)轉(zhuǎn)換到全局事務(wù)或者相反 的轉(zhuǎn)換。如果不使用全局事務(wù),你需要采用一個特定的編碼規(guī)范。幸運的是它非常簡單 。你需要以一個特殊的方式獲得連接資源或者會話資源,允許相關(guān)的 PlatformTransactionManager實現(xiàn)跟蹤連接的使用,并且當(dāng)需要時應(yīng)用事務(wù)管理。
例如,如果使用JDBC,你不應(yīng)該調(diào)用一個數(shù)據(jù)源的?getConnection()方法,而必須使用Spring的?org.springframework.jdbc.datasource.DataSourceUtils類,如下:
Connection conn = DataSourceUtils.getConnection(dataSource);這將提供額外的好處,任何SQLException都被Spring的?CannotGetJdbcConnectionException封裝起來,它屬于Spring的unchecked 的DataAccessException的類層次。這給你比 簡單地從SQLException獲得更多的信息,并且確保跨數(shù)據(jù) 庫,甚至跨越不同持久化技術(shù)的可移植性。
沒有Spring事務(wù)管理的情況下,這也能很好地工作,因此無論使用 Spring事務(wù)管理與否,你都可以使用它。
當(dāng)然,一旦你使用Spring的JDBC支持或Hibernate支持,你將不想使用?DataSourceUtils或其他幫助類,因為與直接使用相關(guān)API相比,你將更樂意使用Spring的抽象。 例如,如果你使用Spring的JdbcTemplate或jdbc.object包來簡化使用JDBC, 正確的數(shù)據(jù)庫連接將自動取得,你不需要書寫任何特殊代碼。
7.3.?編程式事務(wù)管理
Spring提供兩種方式的編程式事務(wù)管理
-
使用TransactionTemplate
-
直接使用一個PlatformTransactionManager實現(xiàn)
我們通常推薦使用第一種方式。
第二種方式類似使用JTA?UserTransaction?API (雖然異常處理少一點麻煩)。
7.3.1.?使用TransactionTemplate
TransactionTemplate采用和其他Spring模板?,如JdbcTemplate和?HibernateTemplate,一樣的方法。它使用回調(diào)方法,把應(yīng)用 程序代碼從處理取得和釋放資源中解脫出來(不再有try/catch/finally)。如同 其他模板,TransactionTemplate是線程安全的。
必須在事務(wù)上下文中執(zhí)行的應(yīng)用代碼看起來像這樣,注意使用?TransactionCallback可以返回一個值:
Object result = tt.execute(new TransactionCallback() {public Object doInTransaction(TransactionStatus status) {updateOperation1();return resultOfUpdateOperation2();} });如果沒有返回值,使用TransactionCallbackWithoutResult, 如下:
tt.execute(new TransactionCallbackWithoutResult() {protected void doInTransactionWithoutResult(TransactionStatus status) {updateOperation1();updateOperation2();} });回調(diào)中的代碼可以調(diào)用TransactionStatus對象的?setRollbackOnly()方法來回滾事務(wù)。
想要使用TransactionTemplate的應(yīng)用類必須能訪問一 個PlatformTransactionManager:通常通過一個JavaBean屬 性或構(gòu)造函數(shù)參數(shù)暴露出來。
使用模擬或樁化的PlatformTransactionManager,單元測試 這些類很簡單。沒有JNDI查找和靜態(tài)魔術(shù)代碼:它只是一個簡單的接口。和平常一樣, 你可以使用Spring簡化單元測試。
7.3.2.?使用PlatformTransactionManager
你也可以使用?org.springframework.transaction.PlatformTransactionManager?直接管理事務(wù)。簡單地通過一個bean引用給你的bean傳遞一個你使用的?PlatformTransactionManager實現(xiàn)。然后, 使用TransactionDefinition和?TransactionStatus對象就可以發(fā)起事務(wù),回滾和提交。
DefaultTransactionDefinition def = new DefaultTransactionDefinition() def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = transactionManager.getTransactionDefinition(def);try {// execute your business logic here } catch (MyException ex) {transactionManager.rollback(status);throw ex; } transactionManager.commit(status);7.4.?聲明式事務(wù)管理
Spring也提供了聲明式事務(wù)管理。這是通過Spring AOP實現(xiàn)的。
大多數(shù)Spring用戶選擇聲明式事務(wù)管理。這是最少影響應(yīng)用代碼的選擇, 因而這是和非侵入性的輕量級容器的觀念是一致的。從考慮EJB CMT和Spring聲明式事務(wù)管理的相似以及不同之處出發(fā)是很有益的。 它們的基本方法是相似的:都可以指定事務(wù)管理到單獨的方法;如果需要可以在事務(wù)上 下文調(diào)用setRollbackOnly()方法。不同之處如下:
-
不象EJB CMT綁定在JTA上,Spring聲明式事務(wù)管理可以在任何環(huán)境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事務(wù)機制一起工作
-
Spring可以使聲明式事務(wù)管理應(yīng)用到普通Java對象,不僅僅是特殊的類,如EJB
-
Spring提供聲明式回滾規(guī)則:EJB沒有對應(yīng)的特性, 我們將在下面討論這個特性。回滾可以聲明式控制,不僅僅是編程式的
-
Spring允許你通過AOP定制事務(wù)行為。例如,如果需要,你可以在事務(wù) 回滾中插入定制的行為。你也可以增加任意的通知,就象事務(wù)通知一樣。使用 EJB CMT,除了使用setRollbackOnly(),你沒有辦法能 夠影響容器的事務(wù)管理
-
Spring不提供高端應(yīng)用服務(wù)器提供的跨越遠(yuǎn)程調(diào)用的事務(wù)上下文傳播。如 果你需要這些特性,我們推薦你使用EJB。然而,不要輕易使用這些特性。通常我 們并不希望事務(wù)跨越遠(yuǎn)程調(diào)用
回滾規(guī)則的概念是很重要的:它們使得我們可以指定哪些異常應(yīng)該發(fā)起自 動回滾。我們在配置文件中,而不是Java代碼中,以聲明的方式指定。因此,雖然我們?nèi)?然可以編程調(diào)用TransactionStatus對象的?setRollbackOnly()方法來回滾當(dāng)前事務(wù),多數(shù)時候我們可以 指定規(guī)則,如MyApplicationException應(yīng)該導(dǎo)致回滾。 這有顯著的優(yōu)點,業(yè)務(wù)對象不需要依賴事務(wù)基礎(chǔ)設(shè)施。例如,它們通常不需要引 入任何Spring API,事務(wù)或其他任何東西。
EJB的默認(rèn)行為是遇到系統(tǒng)異常(通常是運行時異常), EJB容器自動回滾事務(wù)。EJB CMT遇到應(yīng)用程序異常?(除了java.rmi.RemoteException外的checked異常)時不 會自動回滾事務(wù)。雖然Spring聲明式事務(wù)管理沿用EJB的約定(遇到unchecked 異常自動回滾事務(wù)),但是這是可以定制的。
按照我們的測試,Spring聲明式事務(wù)管理的性能要勝過EJB CMT。
通常通過TransactionProxyFactoryBean設(shè)置Spring事務(wù)代理。我們需 要一個目標(biāo)對象包裝在事務(wù)代理中。這個目標(biāo)對象一般是一個普通Java對象的bean。當(dāng)我 們定義TransactionProxyFactoryBean時,必須提供一個相關(guān)的 PlatformTransactionManager的引用和事務(wù)屬性。?事務(wù)屬性含有上面描述的事務(wù)定義。
<bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="target"><ref bean="petStoreTarget"/></property><property name="transactionAttributes"><props><prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="*">PROPAGATION_REQUIRED,readOnly</prop></props></property> </bean>事務(wù)代理會實現(xiàn)目標(biāo)對象的接口:這里是id為petStoreTarget的bean。(使用 CGLIB也可以實現(xiàn)具體類的代理。只要設(shè)置proxyTargetClass屬性為true就可以。 如果目標(biāo)對象沒有實現(xiàn)任何接口,這將自動設(shè)置該屬性為true。通常,我們希望面向接口而不是 類編程。)使用proxyInterfaces屬性來限定事務(wù)代理來代 理指定接口也是可以的(一般來說是個好想法)。也可以通過從?org.springframework.aop.framework.ProxyConfig繼承或所有AOP代理工廠共享 的屬性來定制TransactionProxyFactoryBean的行為。
這里的transactionAttributes屬性定義在?org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource?中的屬性格式來設(shè)置。這個包括通配符的方法名稱映射是很直觀的。注意 insert*的映射的值包括回滾規(guī)則。添加的-MyCheckedException?指定如果方法拋出MyCheckedException或它的子類,事務(wù)將 會自動回滾。可以用逗號分隔定義多個回滾規(guī)則。-前綴強制回滾,+前綴指定提 交(這允許即使拋出unchecked異常時也可以提交事務(wù),當(dāng)然你自己要明白自己 在做什么)。
TransactionProxyFactoryBean允許你通過 “preInterceptors”和“postInterceptors”屬性設(shè)置“前”或“后”通知來提供額外的 攔截行為。可以設(shè)置任意數(shù)量的“前”和“后”通知,它們的類型可以是?Advisor(可以包含一個切入點),?MethodInterceptor或被當(dāng)前Spring配置支持的通知類型 (例如ThrowAdvice,?AfterReturningtAdvice或BeforeAdvice, 這些都是默認(rèn)支持的)。這些通知必須支持實例共享模式。如果你需要高級AOP特 性來使用事務(wù),如有狀態(tài)的maxin,那最好使用通用的?org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean實用代理創(chuàng)建者。
也可以設(shè)置自動代理:配置AOP框架,不需要單獨的代理定義類就可以生成類的 代理。
更多信息和實例請參閱AOP章節(jié)。
無論你是是否是AOP專家,都可以更有效地使用Spring的 聲明式事務(wù)管理。但是,如果你想成為Spring AOP的高級用戶,你會發(fā)現(xiàn)整合聲明 式事務(wù)管理和強大的AOP性能是非常容易的。7.4.1.?BeanNameAutoProxyCreator,另一種聲明方式
TransactionProxyFactoryBean非常有用,當(dāng)事 務(wù)代理包裝對象時,它使你可以完全控制代理。如果你需要用一致的方式(例如,一個 樣板文件,“使所有的方法事務(wù)化”)包裝大量的bean,使用一個?BeanFactoryPostProcessor的一個實現(xiàn),?BeanNameAutoProxyCreator,可以提供另外一種方法, 這個方法在這種簡單的情況下更加簡單。
重述一下,一旦ApplicationContext讀完它的初始化信息,它將初始化所有實 現(xiàn)BeanPostProcessor接口的bean,并且讓它們后處理 ApplicationContext中所有其他的bean。所以使用這種機制,一個正 確配置的BeanNameAutoProxyCreator可以用來后處 理所有ApplicationContext中所有其他的bean(通過名稱來識別),并且把它 們用事務(wù)代理包裝起來。真正生成的事務(wù)代理和使用?TransactionProxyFactoryBean生成的基本一致,這里不再 討論。
讓我們看下面的配置示例:
<!-- Transaction Interceptor set up to do PROPOGATION_REQUIRED on all methods --><bean id="matchAllWithPropReq" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource"><property name="transactionAttribute"><value>PROPAGATION_REQUIRED</value></property></bean><bean id="matchAllTxInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="transactionAttributeSource"><ref bean="matchAllWithPropReq"/></property></bean><!-- One BeanNameAutoProxyCreator handles all beans where we want all methods to use PROPOGATION_REQUIRED --><bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="interceptorNames"><list><idref local="matchAllTxInterceptor"/><idref bean="hibInterceptor"/></list></property><property name="beanNames"><list><idref local="core-services-applicationControllerSevice"/><idref local="core-services-deviceService"/><idref local="core-services-authenticationService"/><idref local="core-services-packagingMessageHandler"/><idref local="core-services-sendEmail"/><idref local="core-services-userService"/></list></property></bean>假設(shè)我們在ApplicationContext中已經(jīng)有一個TransactionManager的實例 ,我們首先要做的使創(chuàng)建一個?TransactionInterceptor實例。 根據(jù)通過屬性傳遞的TransactionAttributeSource接口的一個實現(xiàn),?ransactionInterceptor決定哪個 方法被攔截。這個例子中,我們希望處理匹配 所有方法這種最簡單的情況。這個不是最有效的方式,但設(shè)置非常迅速,因為 我可以使用預(yù)先定義的匹配所有方法的?MatchAlwaysTransactionAttributeSource類。如果我 們需要特定的方式,可以使用?MethodMapTransactionAttributeSource,?NameMatchTransactionAttributeSource或AttributesTransactionAttributeSource。
現(xiàn)在我們已經(jīng)有了事務(wù)攔截器,我們只需把它交給我們定義的?BeanNameAutoProxyCreator實例中,這樣AppliactonContext中 定義的6個bean以同樣的方式被封裝。你可以看到,這 比用TransactionProxyFactoryBean以一種方式單獨封裝6個bean簡潔很 多。封裝第7個bean只需添加一行配置。
你也許注意到可以應(yīng)用多個攔截器。在這個例子中,我們還應(yīng)用了一個 前面定義的HibernateInterceptor?(bean id=hibInterceptor),它為我們管理 Hibernare的會話。
有一件事值得注意,就是在TransactionProxyFactoryBean, 和BeanNameAutoProxyCreator切換時bean的命名。 第一種情況,你只需給你想要包裝的bean一個類似myServiceTarget的id, 給代理對象一個類似myService的id,然后所有代理對象的用戶只需引用代理對象, 如myService(這些是通用命名規(guī)范, 要點是目標(biāo)對象要有和代理對象不同的名稱,并且它們都要在ApplicationContext中可用)。然而, 使用BeanNameAutoProxyCreator時, 你得命名目標(biāo)對象為myService。 然后當(dāng)BeanNameAutoProxyCreator后處理目標(biāo)對象 并生成代理時,它使得代理以和原始對象的名稱被插入到 ApplicationContext中。從這一點看,只有代理(含有被包裝的對象)在ApplicationContext中可用。
7.5.?編程式還是聲明式事務(wù)管理
如果你只有很少的事務(wù)操作,使用編程式事務(wù)管理才是個好主意。例如, 如果你有一個WEB應(yīng)用需要為某些更新操作提供事務(wù),你可能不想用Spring或其 他技術(shù)設(shè)置一個事務(wù)代理。使用?TransactionTemplate可能是個很好的方法。
另一方面,如果你的應(yīng)用有大量的事務(wù)操作,聲明式事務(wù)管理就很有價值。它使得事務(wù)管理從業(yè)務(wù)邏輯分離, 并且Spring中配置也不困難。使用Spring,而不是EJB CMT,聲明式事務(wù)管理配置的成本極大地降低。
7.6.?你需要應(yīng)用服務(wù)器管理事務(wù)嗎?
Spring的事務(wù)管理能力--尤其聲明式事務(wù)管理--極大地改變了J2EE應(yīng)用程序需要 應(yīng)用服務(wù)器的傳統(tǒng)想法。
尤其,你不需要應(yīng)用服務(wù)器僅僅為了通過EJB聲明事務(wù)。事實上,即使你擁 有強大JTA支持的應(yīng)用服務(wù)器,你也可以決定使用Spring聲明式事務(wù)管理提供比 EJB CMT更強大更高效的編程模型。
只有需要支持多個事務(wù)資源時,你才需要應(yīng)用服務(wù)器的JTA支持。許多應(yīng)用沒有 這個需求。例如許多高端應(yīng)用使用單一的,具有高度擴(kuò)展性的數(shù)據(jù)庫,如Oracle 9i RAC。
當(dāng)然也許你需要應(yīng)用服務(wù)器的其它功能,如JMS和JCA。但是如果你只需使用 JTA,你可以考慮開源的JTA實現(xiàn),如JOTM(Spring整合了JOTM)。但是, 2004年早期,高端的應(yīng)用服務(wù)器提供更健壯的XA資源支持。
最重要一點,使用Spring,你可以選擇何時將你的應(yīng)用遷移到完整 應(yīng)用服務(wù)器。使用EJB CMT或JTA都必須書寫代碼使用局部事務(wù), 例如JDBC連接的事務(wù),如果以前需要全局的容器管理的事務(wù),還要面臨著繁重 的改寫代碼的過程,這些日子一去不復(fù)返了。使用Spring只有配置需要改變,你的代碼 不需要修改。
7.7.?公共問題
開發(fā)著需要按照需求仔細(xì)的使用正確的?PlatformTransactionManager實現(xiàn)。
理解Spring事務(wù)抽象時如何和JTA全局事務(wù)一起工作是非常重要的。使用得當(dāng), 就不會有任何沖突:Spring僅僅提供一個簡單的,可以移植的抽象層。
如果你使用全局事務(wù),你必須為你的所有事務(wù)操作使用Spring的?org.springframework.transaction.jta.JtaTransactionManager。 否則Spring將試圖在象容器數(shù)據(jù)源這樣的資源上執(zhí)行局部事務(wù)。這樣的局部事務(wù)沒有任何 意義,好的應(yīng)用服務(wù)器會把這作為一個錯誤。
from:?http://docs.huihoo.com/spring/zh-cn/transaction.html
總結(jié)
以上是生活随笔為你收集整理的Spring - Java/J2EE Application Framework 应用框架 第 7 章 事务管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring - Java/J2EE A
- 下一篇: Spring - Java/J2EE A