2.Spring声明式事务的实现机制
Spring声明式事务是依赖于Spring的AOP代理机制实现的。
首先,标注或XML的元数据声明与AOP结合生成AOP代理,
3.Spring声明式事务的标注(略)
@javax.transaction.Transactional
4.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>设置的事务参数如下: