在Spring框架中,XML配置提供了多种方式来实现事务管理,今天用TransactionProxyFactoryBean实现配置
TransactionProxyFactoryBean
使用TransactionProxyFactoryBean
来创建一个代理bean,该代理bean会为目标bean(在这里是testTransactionService
)的方法调用添加事务管理。
事务管理器定义:
<!-- 定义事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
这里定义了一个事务管理器transactionManager
,它是DataSourceTransactionManager
的一个实例。这个事务管理器将用于处理与数据库相关的事务。dataSource
属性引用了数据源,该数据源在配置中应该已经定义好了。
基础事务代理配置:
<!-- 定义需要进行事务管理的方法 --> <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager" /> </bean>
这里定义了一个基础的事务代理beanbaseTransactionProxy
。这个bean是抽象的(abstract="true"
),意味着它本身不会被实例化,而是作为其他bean的父bean来使用的。它配置了一个transactionManager
属性,引用了前面定义的事务管理器。
具体事务代理配置:
<bean id="testServiceTra" parent="baseTransactionProxy"> <property name="target" ref="testTransactionService" /> <property name="transactionAttributes"> <props> <!-- 指定某个方法进行事务管理 这里是所有--> <prop key="*"> PROPAGATION_REQUIRED,-RRException </prop> </props> </property> </bean>
这里定义了一个具体的事务代理bean
testServiceTra
,它的父bean是baseTransactionProxy
。这个bean的目标bean(即被代理的bean)是testTransactionService
。
transactionAttributes
属性定义了事务的属性。在这个例子中,<prop key="*">
表示这个配置适用于目标bean的所有方法(*
是一个通配符)。PROPAGATION_REQUIRED
表示这些方法需要在事务中运行,如果当前没有事务,就会创建一个新的事务。
-RRException
表示如果方法执行过程中抛出了RRException
异常,那么该异常不会被视为回滚事务的原因。也就是说,即使testTransactionService
的方法在执行过程中抛出了RRException
异常,事务仍然会提交,而不是回滚。
如果想配置其中一个方法或者配置某些名字开头、结尾的方法名
对于特定方法,您可以使用方法的全名作为键。例如,如果testTransactionService
有一个名为testTransactionOne
的方法,并且您想为它配置特定的事务属性,您可以这样写:
<property name="transactionAttributes"> <props> <!-- 指定某个方法进行事务管理 --> <prop key="testTransactionOne">PROPAGATION_REQUIRED</prop> </props> </property>
如果您想为所有以test
开头的方法配置相同的事务属性
您可以使用通配符*
来匹配以approve
开头的任意方法名:
<property name="transactionAttributes"> <props> <!-- 指定某个方法进行事务管理 test开头--> <prop key="test*">PROPAGATION_REQUIRED</prop> </props> </property>
如果您想为所有以Service
结尾的方法配置相同的事务属性
<property name="transactionAttributes"> <props> <!-- 指定某个方法进行事务管理 Service结尾区分大小写--> <prop key="*Service">PROPAGATION_REQUIRED</prop> </props> </property>
请注意,这些键(key)是区分大小写的
如果您想为多个特定方法配置不同的事务属性,您可以添加更多的<prop>
元素,每个元素对应一个方法名或模式:
<property name="transactionAttributes"> <props> <prop key="testTransactionOne">PROPAGATION_REQUIRED</prop> <prop key="testTransactionTwo">PROPAGATION_REQUIRES_NEW</prop> <prop key="testTransactionThree*">PROPAGATION_MANDATORY</prop> </props> </property>
在Spring框架中,事务传播行为定义了当一个事务方法被另一个事务方法调用时,应该如何使用事务。
Spring定义了七种不同的事务传播行为:
- PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务。这是最常用的设置。
- PROPAGATION_REQUIRES_NEW:当前方法必须开启一个新的事务。如果当前存在事务,则挂起该事务。这个传播行为通常用于需要独立事务的情况,例如在一个事务中调用另一个方法,但需要保证被调用方法的事务与当前事务独立。
- PROPAGATION_MANDATORY:表示当前方法必须在事务中运行。如果当前没有事务,将抛出异常。
- PROPAGATION_NESTED:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或者回滚。如果当前没有事务,那么其行为与PROPAGATION_REQUIRED一样。
- PROPAGATION_NEVER:表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则抛出异常。
- PROPAGATION_NOT_SUPPORTED:表示该方法不应该运行在事务中。如果当前存在事务,那么该方法的调用将不会运行在事务中。
- PROPAGATION_SUPPORTS:表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行。
在Spring中,通过TransactionProxyFactoryBean
或@Transactional
注解配置的事务属性,通常适用于代理对象所公开(public)的方法。Spring的AOP(面向切面编程)机制,包括事务管理,主要关注公开的方法调用,因为它们是跨切面的关注点。
对于
private
方法,由于它们不是公开的,因此通常不会被Spring AOP所拦截。Spring的代理是基于Java的接口或类的继承,它只能拦截到通过代理对象调用的公开方法。因此,如果您尝试在private
方法上应用事务属性,这些属性将不会被考虑,因为private
方法调用通常发生在代理创建之前,即目标对象内部。
因此,当您配置事务属性时,应该只关注public
方法。如果您需要为private
方法配置事务,您可能需要重新考虑您的设计,将逻辑移动到public
方法中,或者考虑使用其他机制(如编程式事务管理)来处理这种情况。
这里是一个例子,展示了如何只为public
方法配置事务属性:
<property name="transactionAttributes"> <props> <prop key="publicMethod*">PROPAGATION_REQUIRED</prop> </props> </property>
publicMethod*
模式将匹配所有以publicMethod
开头的public
方法,并应用PROPAGATION_REQUIRED
事务属性。
如果您使用注解来配置事务,情况也是相同的。只有标记了@Transactional
的public
方法才会被Spring拦截并应用事务管理。