在TransactionProxyFactoryBean上有setTransactionAttributeSource()與setTransactionAttributes()方法,它們是用來設定交易屬性的策略實例。
org.springframework.transaction.interceptor.TransactionAttributeSource介面 上有一個getTransactionAttribute()方法,您可以根據傳遞給它的Method實例與Class實例,決定該返回一個什麼內容的 org.springframework.transaction.interceptor.TransactionAttribute實例,一個最簡單 的TransactionAttributeSource實作是 org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource, 對於每一個方法呼叫都會應用交易,它會返回的TransactionAttribute實例之預設傳播行為是PROPAGATION_REQUIRED, 隔離層級為ISOLATION_DEFAULE。
一個應用的例子如下所示:
...
<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.
→ MatchAlwaysTransactionAttributeSource"/>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
...<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.
→ MatchAlwaysTransactionAttributeSource"/>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
您可以使用org.springframework.transaction.interceptor.DefaultTransactionAttribute,並設置自己的交易策略,之後將之設定給TransactionAttributeSource,例如:
...
<bean id="myTransactionAttribute"
class="org.springframework.transaction.
→ interceptor.DefaultTransactionAttribute">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRES_NEW</value>
</property>
<property name="isolationLevelName">
<value>ISOLATION_REPEATABLE_READ</value>
</property>
</bean>
<bean id="transactionAttributeSource"
class="org.springframework.transaction.
→ interceptor.MatchAlwaysTransactionAttributeSource">
<property name="transactionAttribute">
<ref bean="myTransactionAttribute"/>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
...
<bean id="myTransactionAttribute"
class="org.springframework.transaction.
→ interceptor.DefaultTransactionAttribute">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRES_NEW</value>
</property>
<property name="isolationLevelName">
<value>ISOLATION_REPEATABLE_READ</value>
</property>
</bean>
<bean id="transactionAttributeSource"
class="org.springframework.transaction.
→ interceptor.MatchAlwaysTransactionAttributeSource">
<property name="transactionAttribute">
<ref bean="myTransactionAttribute"/>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
...
可以使用org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource來指定某些方法要應用交易,以及要應用的交易策略,例如:
...
<bean id="transactionAttributeSource"
class="org.springframework.transaction.
→ interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="insert*">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
...
<bean id="transactionAttributeSource"
class="org.springframework.transaction.
→ interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="insert*">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
...
在NameMatchTransactionAttributeSource的"properties"屬性上,可以指定方法名稱與交易策略,方法名稱的 指定可以指定全名,也可以使用Wildcard來指定,例如上面的指定中,只要方法名稱以insert為開頭的都會應用相對應的交易策略。
在指定交易策略時,指定的格式如下:
傳播行為,隔離層級,唯讀,+例外, -例外
除了傳播行為一定要設置之外,其它都可選擇性的設置,中間以逗號區隔,例如:
PROPAGATION_REQUIRED,readOnly,-MyCheckedException
MyCheckedException前面加上"-"時,表示發生指定例外時撤消操作,如果前面加上"+",表示發生例外時立即提交。
在比較簡單的設置中,可以僅設置TransactionProxyFactoryBean,並在它的"transactionAttributes"屬性上直接設置要應用交易的方法及交易策略,例如:
...
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
...
<bean id="userDAOProxy"
class="org.springframework.transaction.
→ interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
...
您甚至也可以直接指定TransactionInterceptor,以獲得更多的控制,例如:
...
<bean id="transactionInterceptor"
class="org.springframework.transaction.
→ interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<value>
onlyfun.caterpillar.UserDAO.insert*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.aop.
→ framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
...
<bean id="transactionInterceptor"
class="org.springframework.transaction.
→ interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<value>
onlyfun.caterpillar.UserDAO.insert*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
<bean id="userDAOProxy"
class="org.springframework.aop.
→ framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>onlyfun.caterpillar.IUserDAO</value>
</list>
</property>
<property name="target">
<ref bean="userDAO"/>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
...
選擇哪一種設定方式是需求的問題,您可以嘗試在DeclarativeTransactionDemo專案的Bean 定義檔上設定以上所介紹的方式,基於篇幅的限制,以上僅列出部份的設定內容。