Spring Framework--Data Access(1)--Transaction Management(2) - 声明式事务管理

一、概述

  Spring的声明式事务管理是通过Spring的AOP实现的,Spring的事务管理和EJB CMT类似,都可以在方法级别上定义事务行为,不过他们两者也有区别,表现在:

  (1)EJB CMT是和JTA绑定的,Spring可以在任何环境下工作,包括使用JTA的全局事务环境,已经使用JDBC,JPA,Hibernate或者JDO的本地事务环境。

  (2)你可以在任何类上应用Spring的声明式事务管理,包括一些特定的类,比如EJB。

  (3)Spring提供了一些声明式的回滚规则,而EJB CMT没有。

  (4)Spring可以使用AOP来自定义事务行为,而EJB CMT除了setRollbackOnly()方法外,你不能自定义事务行为。

  (5)Spring不能像一些高端的应用服务器一样,支持跨远程调用的事务上下文传播。如果你需要这个特性,推荐使用EJB,但是这种需求一般很少。

  回滚规则的概念非常重要,它使你能够指定哪些异常(Exception)可以导致事务被回滚。你在配置文件而不是Java代码里指定这些规则,这很重要,因为这样你的业务对象就不需要依赖于事务基础架构,比如不需要导入Spring的事务API或者其他API。

二、理解Spring的声明式事务管理的实现方式

理解Spring是如何支持声明式事务管理最重要的是明白它是通过AOP代理实现的,事务性advice是通过元数据配置的(XML或者java注解)。AOP和事务性的元数据的组合产生了AOP的代理,代理通过使用TransactionInterceptor和一个合适的PlatformTransactionManager实现来在方法调用的周围驱动事务。概念上,在事务性代理上调用一个方法如下图所示:

举例来说,假设有如下接口及其实现:

// the service interface that we want to make transactional
package x.y.service;
public interface FooService {
  Foo getFoo(String fooName);
  Foo getFoo(String fooName, String barName);
  void insertFoo(Foo foo);
  void updateFoo(Foo foo);
}

// an implementation of the above interface
package x.y.service;
public class DefaultFooService implements FooService {
  public Foo getFoo(String fooName) {
    throw new UnsupportedOperationException();
  }
  public Foo getFoo(String fooName, String barName) {
    throw new UnsupportedOperationException();
  }
  public void insertFoo(Foo foo) {
    throw new UnsupportedOperationException();
  }
  public void updateFoo(Foo foo) {
    throw new UnsupportedOperationException();
  }
}

假设现在我们要使前两个方法在一个只读的事务上下文中执行,后两个方法在读写事务上下文中执行,那么我们可以使用如下XML配置:

<!-- from the file context.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 service object that we want to make transactional -->
  <bean id="fooService" class="x.y.service.DefaultFooService"/>
  <!-- the transactional advice (what happens; see the <aop:advisor/> bean below) -->   <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 (see below) -->       <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>
  <!-- don't forget the DataSource -->   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroymethod="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>
  <!-- similarly, don't forget the PlatformTransactionManager -->   <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">     <property name="dataSource" ref="dataSource"/>   </bean>
  <!-- other <bean/> definitions here --> </beans>

该配置中的<tx:advice>的意思是说,所有以get开头的方法在一个只读的事务上下文中执行,其他所有方法在读写的事务上下文中执行。

posted on 2014-04-23 18:10  leungrs  阅读(328)  评论(0编辑  收藏  举报