<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>


    posts - 15,  comments - 34,  trackbacks - 27

    Chapter 7. 事務(wù)管理

    7.1. Spring事務(wù)抽象

    Spring提供了一致的事務(wù)管理抽象。這個抽象是Spring最重要的抽象之一, 提供如下的優(yōu)點(diǎn):

    • 提供跨越不同的事務(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ù)由應(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ù)有一個顯著的不利方面,代碼需要使用JTA:一個笨重的API(部分是 因?yàn)樗漠惓DP停4送猓琂TA UserTransaction通常需 要從JNDI獲得,意味著我需要同時使用JNDI和JTA來使用 JTA。顯然全部使用全局事務(wù)限制了應(yīng)用代碼的重用性,因?yàn)镴TA通常只在應(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實(shí)現(xiàn)業(yè)務(wù)邏輯時才能使用,或者至少使用在一個事務(wù)化EJB的外觀 (Fa?ade)后。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 接口表達(dá),如下:

    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 的實(shí)現(xiàn)定義和其他Spring IoC容器中的對象一樣。這個好處使得即使使用JTA這也 是一個很有價值的抽象:事務(wù)代碼可以比直接使用JTA更加容易測試。

    繼續(xù)Spring哲學(xué),TransactionException是不被檢查的。 低層的事務(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ù)中運(yùn)行。但是,如果當(dāng)一個事務(wù)上下文已經(jīng)存在時, 一個事務(wù)方法被執(zhí)行,有幾個選項(xiàng)可以指定其行為:例如,簡單地在現(xiàn)有的 事務(wù)中運(yùn)行(大多數(shù)情況);或者掛起現(xiàn)有事務(wù),創(chuàng)建一個新的事務(wù)。 Spring提供EJB CMT中熟悉的事務(wù)傳播選項(xiàng)。

    • 事務(wù)超時: 事務(wù)在超時前能運(yùn)行多 久(自動被底層的事務(wù)基礎(chǔ)設(shè)施回滾)。

    • 只讀狀態(tài): 只讀事務(wù)不修改任何數(shù) 據(jù)。只讀事務(wù)在某些情況下(例如當(dāng)使用Hibernate時)可能是最佳選擇。

    這些設(shè)置反映了標(biāo)準(zhǔn)概念。如果需要,請查閱討論事務(wù)隔離層次和其他核心事 務(wù)概念的資源:理解這些概念是使用Spring和其他事務(wù)管理解決方案的基本要素。

    TransactionStatus接口為處理事務(wù)的代碼提供一個簡單 的控制事務(wù)的執(zhí)行和查詢事務(wù)狀態(tài)方法。這個概念應(yīng)該是熟悉的,因?yàn)樗鼈冊谒?有的事務(wù)API中是相同的:

    public interface TransactionStatus {

        boolean isNewTransaction();

        
    void setRollbackOnly();

        boolean isRollbackOnly();
    }

    但是使用Spring事務(wù)管理時,定義 PlatformTransactionManager的實(shí)現(xiàn)是基本方式。在好的Spring 風(fēng)格中,這個重要定義使用IoC實(shí)現(xiàn)。

    PlatformTransactionManager實(shí)現(xiàn)通常需要了解它們工作 的環(huán)境:JDBC、JTA、Hibernate等等。

    下面來自Spring范例jPetstore中的 dataAccessContext-local.xml的例子展示了一個局部 PlatformTransactionManager實(shí)現(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, 我們需要使用容器數(shù)據(jù)源,通過JNDI獲得,還需要一個JtaTransactionManager實(shí) 現(xiàn),JtaTransactionManager不需要知道數(shù)據(jù)源,或任何其他指定資源,因?yàn)樗鼘?使用容器的全局事務(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 范例中的例子展現(xiàn)的一樣。

    在這種情況下,我們需要定義一個Hibernate的LocalSessionFactory,應(yīng)用程 序?qū)⑹褂盟@得Hibernate Sessions。

    數(shù)據(jù)源bean定義和上面例子類似,這里不在羅列(如果這是一個不需事務(wù)的容 器數(shù)據(jù)源,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配置的其他資源一樣的,因?yàn)樗鼈兌际侨质聞?wù)。

    在所有這些情況下,應(yīng)用程序代碼不需要任何更改。我們可以僅僅更改配置 來更改事務(wù)方式,甚至這些更改意味這從局部事務(wù)轉(zhuǎn)換到全局事務(wù)或者相反方向 的轉(zhuǎn)換。

    如果不使用全局事務(wù),你需要采用一個特定的代碼規(guī)范。幸運(yùn)的這是非常簡單 的。你需要以一個特定的方式獲得連接或者session資源,允許相關(guān)的 PlatformTransactionManager實(shí)現(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的不被檢查 的DataAccessException的類層次之一包裝起來。這給你比 簡單地從SQLException獲得更多的信息,并且確保跨數(shù)據(jù) 庫,甚至跨越不同持久化技術(shù)的可移植性。

    這將很好地在沒有Spring事務(wù)管理的情況下工作,因此無論使用還是不使用 Spring事務(wù)管理,你都可以使用它。

    當(dāng)然,一旦你使用Spring JDBC支持或Hibernate支持,你將不必使用 DataSourceUtils或其他幫助類,因?yàn)槟銓⒈戎苯邮褂孟嚓P(guān) API更加愉快地使用Spring的抽象。例如,如果你使用Spring JdbcTemplate或 jdbc.object包來簡化使用JDBC,正確的數(shù)據(jù)庫連接將自動取得,你不需要書寫 任何特定代碼。

    7.3. 編程式事務(wù)管理

    Spring提供兩種方式的編程式事務(wù)管理

    • 使用TransactionTemplate

    • 直接使用PlatformTransactionManager一個實(shí)現(xiàn)

    我們通常推薦使用第一種方式。

    第二種方式類似使用JTA UserTransaction API (雖然異常處理少一點(diǎn)麻煩)。

    7.3.1. 使用TransactionTemplate

    TransactionTemplate采用和其他Spring模板 JdbcTemplateHibernateTemplate一樣的方法。它使用回調(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引用傳遞一個你使用的 PlatformTransactionManager實(shí)現(xiàn)到你的bean,然后, 使用TransactionDefinitionTransactionStatus對象就可以發(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實(shí)現(xiàn)的。

    大多數(shù)Spring用戶選擇聲明式事務(wù)管理。這是最少的影響應(yīng)用代碼的選擇, 因而這是和非入侵的輕量級容器的觀念是一致的。

    從考慮EJB CMT和Spring聲明式事務(wù)管理的相似以及不同之處出發(fā)是很有益的。 基本方法是一致的:都可以指定事務(wù)管理到單獨(dú)的方法;如果需要可以在事務(wù)上 下文調(diào)用setRollbackOnly()方法。不同之處:

    • 不同于EJB CMT綁定在JTA上,Spring聲明式事務(wù)管理可以在任何環(huán)境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事務(wù)機(jī)制一起工作

    • Spring可以使聲明式事務(wù)管理應(yīng)用到POJO,不僅僅是特定的類,如EJB

    • Spring提供聲明式回滾規(guī)則:EJB沒有對應(yīng)的特性, 我們將在下面討論這個特性。回滾可以聲明式控制,不僅僅是編程式的

    • Spring通過AOP提供定制事務(wù)行為的機(jī)會。例如,如果需要,你可以在事務(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)點(diǎn),業(yè)務(wù)對象不需要依賴事務(wù)基礎(chǔ)設(shè)施。例如,他們通常不需要引 入任何Spring API,事務(wù)或其他任何東西。

    EJB的默認(rèn)行為是遇到系統(tǒng)異常(通常是運(yùn)行時異常) EJB容器自動回滾事務(wù)。EJB CMT遇到應(yīng)用程序異常 (除了java.rmi.RemoteException外被檢查的異常)時不 會自動回滾事務(wù)。雖然Spring聲明式事務(wù)管理沿用EJB CMT約定(遇到不被檢查的 異常自動回滾事務(wù)),但是這是可以定制的。

    按照我們的基準(zhǔn),Spring聲明式事務(wù)管理的性能要勝過EJB CMT。

    通常設(shè)置Spring事務(wù)代理的方法是通過TransactionProxyFactoryBean。我們需 要一個包裝在事務(wù)代理中目標(biāo)對象。這個目標(biāo)對象一般是一個POJO的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ù)代理會實(shí)現(xiàn)目標(biāo)對象的接口:這里是id為petStoreTarget.的bean(使用 CGLIB可以實(shí)現(xiàn)具體類的代理,只要設(shè)置proxyTargetClass屬性為true就可以。這 將自動設(shè)置,如果目標(biāo)對象沒有實(shí)現(xiàn)任何接口。通常,我們希望面向接口而不是 類編程)。可以(一般來說是好的想法)限定事務(wù)代理使用proxyInterfaces來代 理指定的接口。也可以通過繼承至 org.springframework.aop.framework.ProxyConfig幾個屬 性來定制TransactionProxyFactoryBean的行為,并在所有的AOP代理工廠中共享。

    這里的transactionAttributes通過定在 org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 類中的屬性格式來設(shè)置。這個包括通配符的方法名稱映射是很直觀的。注意 insert*的映射的值包括回滾規(guī)則。添加-MyCheckedException 指定如果方法拋出MyCheckedException或它的子類,事務(wù)將 會自動回滾。可以指定個回滾規(guī)則,用逗號分隔。-前綴強(qiáng)制回滾,+前綴指定提 交(這允許即使拋出未被檢查的異常時也可以提交事務(wù),當(dāng)然你自己要明白自己 在做什么)。

    TransactionProxyFactoryBean允許你通過 “preInterceptors”和“postInterceptors”屬性設(shè)置“前”或“后”通知來提供額外的 攔截行為。可以設(shè)置任意數(shù)量的“前”和“后”通知,它們的類型可以是 Advisor(可以包含一個pointcut), MethodInterceptor或被當(dāng)前Spring配置支持的通知類型 (例如ThrowAdviceAfterReturningtAdviceBeforeAdvice, 這些都是默認(rèn)支持的)。這些通知必須支持實(shí)例共享模式。如果你需要高級AOP特 性來使用事務(wù),如有狀態(tài)的混入,那最好使用通用的 org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean代理創(chuàng)建者。

    也可以設(shè)置自動代理:配置AOP框架,不需要單獨(dú)的代理定義類就可以生成類的 代理。

    更多信息和實(shí)例請參閱AOP章節(jié)。

    你不需要成為AOP專家,當(dāng)然,了解更多的AOP知識,可以更有效地使用Spring 聲明式事務(wù)管理。但是,如果你想成為Spring AOP的高級用戶,你會發(fā)現(xiàn)整合聲明 式事務(wù)管理和強(qiáng)大的AOP性能是非常容易的。

    7.4.1. BeanNameAutoProxyCreator,另一種聲明方式

    TransactionProxyFactoryBean非常有用,并且當(dāng)事 務(wù)代理包裝對象時,你有全部的支配權(quán)。如果你需要用一致的方式(例如,一個 樣板文件,“使所有的方法事務(wù)化”)包裝大量的bean,使用一個 BeanFactoryPostProcessor調(diào)用 BeanNameAutoProxyCreator可以提供另外一種方法, 一個在這種簡單的情況下更加簡化的方法。

    重述一下,一旦ApplicationContext讀完它的初始化信息,它將初始化所有實(shí) 現(xiàn)BeanPostProcessor的bean,并且給所有其他 ApplicationContext中beans一個后期處理的機(jī)會。所以使用這種機(jī)制,一個正 確配置的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è)我們已經(jīng)有一個TransactionManager的實(shí)例 在ApplicationContext中,我們首先要做的使創(chuàng)建一個 TransactionInterceptor實(shí)例。 ransactionInterceptor基于一個實(shí)現(xiàn) TransactionAttributeSource接口的對象決定哪個 方法被攔截, 這個對象作為屬性傳遞進(jìn)來的。這個例子中,我們希望處理匹配 所有方法這種最簡單的情況。這個不是最有效的方式,但設(shè)置非常迅速,因?yàn)?我可以使用預(yù)先定義的匹配所有方法的 MatchAlwaysTransactionAttributeSource類。如果我 們需要特定的方式,可以使用 MethodMapTransactionAttributeSourceNameMatchTransactionAttributeSourceAttributesTransactionAttributeSource

    現(xiàn)在我們已經(jīng)有了事務(wù)攔截器,我們只需把它和另外6個我們希望以一致方式 包裝的AppliactonContext中的bean一起放到我們定義的 BeanNameAutoProxyCreator實(shí)例中。你可以看到,這 個結(jié)果比用TransactionProxyFactoryBean以一種方式單獨(dú)包裝6個bean簡捷很 多。包裝第7個bean只需添加一行配置。

    你也許注意到可以應(yīng)用多個攔截器。在這個例子中,我們也可以應(yīng)用一個預(yù) 先定義的HibernateInterceptor (bean id=hibInterceptor),這個為我們管理 Hibernare的Sessions。

    有一件事值得注意,就是在TransactionProxyFactoryBean, 和BeanNameAutoProxyCreator切換時bean的名稱。 第一種情況,你只需給你想要包裝的bean一個類似 myServiceTarget的id, 給代理對象一個類似myService的id, 然后所有代理對象的用戶只需引用代理對象, 如myService(這些是通用命名規(guī)范, 要點(diǎn)是目標(biāo)對象要有和代理對象不同的名稱, 并且他們都要在ApplicationContext中可用)。然而, 使用BeanNameAutoProxyCreator時, 你命名目標(biāo)對象為myService。 然后當(dāng)BeanNameAutoProxyCreator后期處理目標(biāo)對象 并生成代理時,它導(dǎo)致代理以和原始對象相同的名稱被插入到 ApplicationContext中。從這一點(diǎn)看,只有代理(含有被包裝的對象)在Application中可用。

    7.5. 編程式還是聲明式事務(wù)管理

    如果你只有很少的事務(wù)操作,使用編程式事務(wù)管理是很好的主意。例如, 如果你有一個WEB應(yīng)用需要為某些更新操作提供事務(wù),你可能不想用Spring或其 他技術(shù)設(shè)置一個事務(wù)代理。使用 TransactionTemplate可能是個很好的方法。

    另一方面,如果你的應(yīng)用有大量的事務(wù)操作,編程式(譯注:應(yīng)為聲明式, 疑是作者筆誤)事務(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ù)。事實(shí)上,即使你擁 有強(qiáng)大JTA支持的應(yīng)用服務(wù)器,你也可以決定使用Spring聲明式事務(wù)管理提供比 EJB CMT更強(qiáng)大更高效的編程模型。

    只有需要支持多個事務(wù)資源時你才需要應(yīng)用服務(wù)器的JTA支持。許多應(yīng)用沒有 這個需求。例如許多高端應(yīng)用使用單一的高度可升級的數(shù)據(jù)庫,如Oracle 9i RAC。

    當(dāng)然也許你需要其他應(yīng)用服務(wù)器的功能,如JMS和JCA。但是如果你只需使用 JTA,你可以考慮開源的JTA實(shí)現(xiàn),如JOTM(Spring整合了JOTM)。但是, 2004年早期,高端的應(yīng)用服務(wù)器提供更健壯的XA資源支持。

    最重要一點(diǎn),使用Spring,你可以選擇何時將你的應(yīng)用遷移到完整 應(yīng)用服務(wù)器。除了使用EJB CMT和JTA只能書寫代碼使用局部事務(wù), 例如JDBC連接的事務(wù),而且如果曾經(jīng)需要全局的容器管理的事務(wù),還面臨著繁重 的改寫過程,這些日子一去不復(fù)返了。使用Spring只有配置需要改變,你的代碼 不需要。

    7.7. 公共問題

    開發(fā)著需要按照需求仔細(xì)的使用正確的 PlatformTransactionManager實(shí)現(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ù)器會把這作為一個錯誤。

    posted on 2005-02-04 11:12 jacky 閱讀(701) 評論(0)  編輯  收藏 所屬分類: Open source
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(10)

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    java

    搜索

    •  

    最新評論


    主站蜘蛛池模板: 亚洲欧洲国产日韩精品| 永久在线免费观看| 亚洲色成人四虎在线观看| 亚洲AV综合色区无码一区爱AV| 精品久久免费视频| 免费福利网站在线观看| 无码A级毛片免费视频内谢| 一级毛片免费一级直接观看| 亚洲视频免费一区| 国产精品无码免费专区午夜| 久久亚洲免费视频| 午夜高清免费在线观看| 2021免费日韩视频网| 日韩免费的视频在线观看香蕉| 国产精品一区二区三区免费| 国产精品亚洲小说专区| 亚洲熟妇无码一区二区三区| 亚洲冬月枫中文字幕在线看| 亚洲精品福利网站| 亚洲视频在线观看一区| 亚洲av女电影网| 西西人体44rt高清亚洲| 国产成人亚洲综合色影视| 亚洲精品高清无码视频| 亚洲av伊人久久综合密臀性色| 日本亚洲国产一区二区三区| 国产专区一va亚洲v天堂| 亚洲精品一级无码中文字幕| 伊人久久亚洲综合影院| 亚洲国产一区二区三区| 亚洲精品无码久久久| 久久久久久亚洲精品不卡| 伊人婷婷综合缴情亚洲五月| 中文字幕亚洲天堂| 国产亚洲精AA在线观看SEE| 精品亚洲一区二区| 日韩亚洲Av人人夜夜澡人人爽| 亚洲最新永久在线观看| 亚洲日本在线观看网址| 亚洲综合校园春色| 久久精品国产亚洲AV高清热|