5.5 Spring事務支持

聲明式事務管理的配置方式,一般有如下4種:spring

① 使用TransactionProxyFactoryBean爲目標Bean生成事務代理的配置。此方式是最傳統、配置文件最臃腫、最難以閱讀的方式。session

② 採用Bean繼承的事務代理配置方式,比較簡潔,但依然是增量式配置。框架

③ 採用BeanNameAutoProxyCreator,根據Bean Name自動生成事務代理的方式。這是直接利用Spring的AOP框架配置事務代理的方式,須要對Spring的AOP框架有所理解。但這種方式避免了增量式配置,效果很是不錯ui

④ 採用DefaultAdvisorAutoProxyCreator,直接利用Spring的AOP框架配置事務代理的方式,效果很是不錯,只是這種配置方式的可讀性不如第3種方式spa

5.5.1  使用TransactionProxy FactoryBean生成事務代理

        採用這種方式的配置,配置文件增長得很是快。每一個Bean須要兩個Bean配置,一個是目標Bean,另一個是使用TransactionProxyFactoryBean配置一個代理Bean。這是一種最原始的配置方式,其配置文件。.net

<?xml version="1.0" encoding="UTF-8"?>
<!--Spring配置文件的文件頭,包含DTD等信息-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
...
    <!-- 定義事務管理器,使用適用於Hibernate的事務管理器-->
    <bean id="transactionManager"
             class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <!--HibernateTransactionManager bean須要依賴注入一個SessionFactory bean的引用-->
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
    <bean id="xsDao"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!--爲事務代理Bean注入事務管理器-->
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <!--設置事務屬性-->
        <property name="transactionAttributes"> 
            <props>
            <!--全部以save開頭的方法,採用required的事務策略,而且只讀-->
                <prop key="save*">PROPAGATION_REQUIRED,readOnly</prop> 
                <!-- 其餘方法,採用required的事務策略 -->
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props> 
        </property>
        <!--爲事務代理Bean設置目標Bean -->
        <property name="target"> 
            <!--採用嵌套Bean配置目標Bean-->
            <bean class="org.dao.imp.XsDaoImp">
                <!-- 爲DAO bean注入SessionFactory引用-->
                <property name="sessionFactory">
                    <ref local="sessionFactory"/>
                </property>
            </bean>
        </property> 
    </bean>
</beans>

5.5.2  利用繼承簡化配置

        對於這種狀況,Spring提供了Bean與Bean之間的繼承,能夠簡化配置。將大部分的通用配置,配置成事務模板。而實際的事務代理Bean,則繼承事務模板。這種配置方式能夠減小部分配置代碼,其配置文件。hibernate

<?xml version="1.0" encoding="UTF-8"?>
<!--Spring配置文件的文件頭,包含DTD等信息-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    ...
    <!-- 定義事務管理器,使用適用於Hibernate的事務管理器-->
    <bean id="transactionManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <!-- HibernateTransactionManager bean須要依賴注入一個SessionFactory bean的引用-->
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
    <!-- 配置事務模板,模板Bean被設置成abstract bean,保證不會被初始化-->
    <bean id="txBase"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
            lazy-init="true" abstract="true">
        <!--爲事務模板注入事務管理器-->
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <!--設置事務屬性-->
        <property name="transactionAttributes"> 
            <props> 
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props> 
        </property>
    </bean>
    <!-- 實際的事務代理Bean-->
    <bean id="xsDao" parent="txBase">
    <!--採用嵌套Bean配置目標Bean -->
    <property name="target">
        <bean class="org.dao.imp.XsDaoImp ">
            <property name="sessionFactory">
                <ref local="sessionFactory"/>
            </property>
        </bean>
    </property>
    </bean>
</beans>

5.5.3  用BeanNameAutoProxy Creator自動建立事務代理

        下面介紹一種優秀的事務代理配置策略:採用這種配置策略,徹底能夠避免增量式配置,全部的事務代理由系統自動建立。容器中的目標Bean自動消失,避免須要使用嵌套Bean來保證目標Bean不可被訪問。下面是採用BeanNameAutoProxyCreator配置事務代理的配置文件。代理

<?xml version="1.0" encoding="UTF-8"?>
<!--Spring配置文件的文件頭,包含DTD等信息-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
     "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
...
    <!--定義事務管理器,使用適用於Hibernate的事務管理器-->
    <bean id="transactionManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <!-- HibernateTransactionManager bean須要依賴注入一個SessionFactory bean的引用-->
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
    <!--配置事務攔截器-->
    <bean id="transactionInterceptor"
            class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <!--事務攔截器Bean須要依賴注入一個事務管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <!-- 下面定義事務傳播屬性-->
            <props>
                <prop key="save*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!-- 定義BeanNameAutoProxyCreator,該Bean無需被引用,所以沒有id屬性,這個Bean根據事務攔截器爲目標Bean自動建立事務代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <!-- 指定對知足哪些bean name的bean自動生成業務代理 -->
        <property name="beanNames">
            <!--下面是全部須要自動建立事務代理的Bean-->
            <list>
                <value>xsDao</value>
            </list>
            <!--此處可增長其餘須要自動建立事務代理的Bean-->
        </property>
        <!--下面定義BeanNameAutoProxyCreator所需的事務攔截器-->
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value> 
                <!-- 此處可增長其餘新的interceptor -->
            </list>
        </property>
    </bean>
    <!--定義DAO Bean,由BeanNameAutoProxyCreator自動生成事務代理-->
    <bean id="xsDao" class="org.dao.imp.XsDaoImp">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>
</beans>

        TranscationInterceptor是一個事務攔截器Bean,須要傳入一個TransactionManager的引用。配置中使用Spring依賴注入該屬性,事務攔截器的事務屬性經過transactionAttributes來指定,該屬性有props子元素,配置文件中定義了2個事務傳播規則。
code

5.5.4  用DefaultAdvisorAuto ProxyCreator自動建立事務代理

        採用DefaultAdvisorAutoProxyCreator的事務代理配置方式更加簡單,這個代理生成器自動搜索Spring容器中的Advisor,併爲容器中全部的Bean建立代理。相對前一種方式,這種方式的可讀性不如前一種直觀,因此仍是推薦採用前一種配置方式。下面是該方式下的配置文件。orm

<?xml version="1.0" encoding="UTF-8"?>
<!--Spring配置文件的文件頭,包含DTD等信息-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  ...
  <!--定義事務管理器,使用適用於Hibernate的事務管理器-->
  <bean id="transactionManager"
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <!-- HibernateTransactionManager bean須要依賴注入一個SessionFactory bean的引用-->
    <property name="sessionFactory"><ref local="sessionFactory"/></property>
  </bean>
  <!--配置事務攔截器-->
  <bean id="transactionInterceptor"
      class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <!--事務攔截器Bean須要依賴注入一個事務管理器 -->
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
      <!--下面定義事務傳播屬性-->
      <props>
        <prop key="save*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="*">PROPAGATION_REQUIRED</prop>
      </props>
    </property>
  </bean>
  <!--定義事務Advisor-->
  <bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
    <!--定義Advisor時,必須傳入interceptor-->
    <property name="transactionInterceptor" ref="transactionInterceptor"/>
  </bean>
  <!-- DefaultAdvisorAutoProxyCreator搜索容器中的Advisor,併爲每一個Bean建立代理 -->
  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
    <!--定義DAO Bean,由Default Advisor AutoProxyCreator自動生成事務代理-->
  <bean id="xsDao" class="org.dao.imp.XsDaoImp">
    <property name="sessionFactory">
      <ref local="sessionFactory"/>
    </property>
  </bean>
</beans>

        無論是哪一種方式,都定義了事務傳播的屬性,下面具體介紹事務傳播的種類

        Spring在TransactionDefinition接口中規定了7種類型的事務傳播行爲,它們規定了事務方法和事務方法發生嵌套調用時事務如何進行傳播。

  • PROPAGATION_REQUIRED:若是當前沒有事務,就新建一個事務; 

  • PROPAGATION_SUPPORTS:支持當前事務。若是當前沒有事務,就以非事務方式執行

  • PROPAGATION_MANDATORY:使用當前的事務。若是當前沒有事務,就拋出異常

  • PROPAGATION_REQUIRES_NEW新建事務。若是當前存在事務,把當前事務掛起

  • PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起

  • PROPAGATION_NEVER:以非事務方式執行。 

  • PROPAGATION_NESTED:若是當前存在事務,則在嵌套事務內執行。


附:目錄《JavaEE基礎實用教程》筆記說明

相關文章
相關標籤/搜索