1.Spring声明式事务与JavaEE CMT的对比
JavaEE CMT依赖JTA事务API,Spring声明式事务可以依赖多种事务API
JavaEE CMT只能用于EJB组件,Spring声明式事务可以用于任何类
JavaEE CMT支持事务上下文的跨远程调用传播,Spring事务无能为力
JavaEE CMT只有遇到java.rmi.RemoteException异常时才回滚事务;Spring声明式事务默认与JavaEE CMT一致,但还可以通过声明式的事务回滚规则定制回滚事务的条件
然后,AOP代理再通过org.springframework.transaction.interceptor.TransactionInterceptor和具体的PlatformTransactionManager实现类实现对方法调用的事务操作。
JavaEE CMT依赖JTA事务API,Spring声明式事务可以依赖多种事务API
JavaEE CMT只能用于EJB组件,Spring声明式事务可以用于任何类
JavaEE CMT支持事务上下文的跨远程调用传播,Spring事务无能为力
JavaEE CMT只有遇到java.rmi.RemoteException异常时才回滚事务;Spring声明式事务默认与JavaEE CMT一致,但还可以通过声明式的事务回滚规则定制回滚事务的条件
2.Spring声明式事务的实现机制
Spring声明式事务是依赖于Spring的AOP代理机制实现的。
首先,标注或XML的元数据声明与AOP结合生成AOP代理,然后,AOP代理再通过org.springframework.transaction.interceptor.TransactionInterceptor和具体的PlatformTransactionManager实现类实现对方法调用的事务操作。
3.Spring声明式事务的标注(略)
@javax.transaction.Transactional4.Spring声明式事务的XML配置
<!-- from the file 'applicationContext.xml' -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- this is the object that we want to be made transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- the transactional advice -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the FooService interface -->
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
</aop:config>
<!-- the DataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<!-- the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- other <bean/> definitions here -->
</beans>
说明:
x.y.service.FooService是一个接口,其中定义的逻辑方法将被加入到事务的操作中。x.y.service.DefaultFooService是FooService接口的一个实现。
将逻辑方法加入到事务操作中,是通过<tx:advice>通知实现的。<tx:advice>不仅通过transaction-manager属性指明使用的事务管理器,而且通过<tx:method>子元素指出加入到事务操作中的逻辑方法。
那么逻辑方法究竟什么时候被加入到事务中执行呢?通过<aop:config>给出,其<aop:pointcut>给出进入事务执行的条件,<aop:advisor>则将逻辑方法和进入事务执行的条件结合起来。
默认,在事务执行过程中,只有发生java.rmi.RemoteException异常才会回滚事务。
在定义事务通知<tx:advice>通知时,可以为要加入到事务中的逻辑方法指定回滚的异常,即发生指定异常即回滚该逻辑方法,示例如下:
<tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundException"/>
此外,还可以为不同的逻辑方法设置不同的进入事务执行的条件,示例如下:
<aop:config>
<aop:pointcut id="defaultServiceOperation" expression="execution(* x.y.service.*Service.*(..))"/>
<aop:pointcut id="noTxServiceOperation" expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
<aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
</aop:config>
<tx:advice id="defaultTxAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="noTxAdvice">
<tx:attributes>
<tx:method name="*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
5.补充说明<tx:advice>的设置
默认情况下<tx:advice>设置的事务参数如下:
- 事务操作为可读写,即read-only="false"
- 事务隔离级别为DEFAULT,即isolation="DEFAULT"
- 事务传播类型为REQUIRED,即propagation="REQUIRED"
- 事务超时为-1,即timeout=-1,即表示采用执行事务的系统的设置
- 事务回滚的异常为java.rmi.RemoteException