聲明式事務管理的配置方式,一般有如下4種:spring
① 使用TransactionProxyFactoryBean爲目標Bean生成事務代理的配置。此方式是最傳統、配置文件最臃腫、最難以閱讀的方式。session
② 採用Bean繼承的事務代理配置方式,比較簡潔,但依然是增量式配置。框架
③ 採用BeanNameAutoProxyCreator,根據Bean Name自動生成事務代理的方式。這是直接利用Spring的AOP框架配置事務代理的方式,須要對Spring的AOP框架有所理解。但這種方式避免了增量式配置,效果很是不錯。ui
④ 採用DefaultAdvisorAutoProxyCreator,直接利用Spring的AOP框架配置事務代理的方式,效果很是不錯,只是這種配置方式的可讀性不如第3種方式。spa
採用這種方式的配置,配置文件增長得很是快。每一個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>
對於這種狀況,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>
下面介紹一種優秀的事務代理配置策略:採用這種配置策略,徹底能夠避免增量式配置,全部的事務代理由系統自動建立。容器中的目標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
採用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:若是當前存在事務,則在嵌套事務內執行。