ITEEDU

TransactionAttributeSource、 TransactionAttribute

在 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>
...

您可以使用 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>
...

可以使用 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>
...

在 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>
...

您甚至也可以直接指定 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>
...

选择哪一种设定方式是需求的问题,您可以尝试在 DeclarativeTransactionDemo 专案的 Bean 定 义档上设定以上所介绍的方式,基于篇幅的限制,以上仅列出部份的设定内容。