详解阿里P7架构师是怎么在Spring中实现事务暂停( 二 )


代理的具体事务行为会由为根据特定的方法或方法命名模式而定义的事务属性来驱动,就像下面的例子所示:
清单3:
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><prop key="store*">PROPAGATION_REQUIRED</prop>Key属性决定代理将为方法提供什么样的事务行为 。这个属性的最重要部分就是事务传播行为 。下面是一些可选的属性值:

  1. PROPAGATION_REQUIRED --支持当前的事务,如果不存在就创建一个新的 。这是最常用的选择 。
  2. PROPAGATION_SUPPORTS --支持当前的事务,如果不存在就不使用事务 。
  3. PROPAGATION_MANDATORY --支持当前的事务,如果不存在就抛出异常 。
  4. PROPAGATION_REQUIRES_NEW --创建一个新的事务,并暂停当前的事务(如果存在) 。
  5. PROPAGATION_NOT_SUPPORTED --不使用事务,并暂停当前的事务(如果存在) 。
  6. PROPAGATION_NEVER --不使用事务,如果当前存在事务就抛出异常 。
  7. PROPAGATION_NESTED --如果当前存在事务就作为嵌入事务执行,否则与PROPAGATION_REQUIRED类似 。
前6个事务策略与EJB的CMT类似,而且使用相同的常量名,因此对EJB开发人员来说是很亲切的 。第7个策略PROPAGATION_NESTED是Spring提供的一个变体:他需要事务管理器(如DataSourceTransactionManager)提供类似JDBC3.0那样的保存点API来嵌套事务行为或者通过
JTA支持嵌套事务 。
事务属性中的readOnly标识指示相应的事务应该作为一个只读事务来优化 。这是一个优化提示:一些事务策略在这种情况下可以得到很好的性能优化,如使用ORM工具如Hibernate或TopLink时避免脏数据检查(“flush”尝试) 。
在事务属性中还有一个“timeout”选项来定义事务的超时秒数 。在JTA中,这个属性会简单地传递给J2EE服务器的事务协调器并被正确地解释 。
使用事务代理在运行时,客户端会取得一个“clinic”引用并转换为Clinic接口,然后调用如loadPet或storePet方法 。这就隐式地使用了Spring的事务代理,通过“事务解释器”在目标对象中注册;这样一个新的事务就创建了,然后具体的工作就会代理给JdbcClinic的目标方法 。
图1示例了一个使用“建议链”并到达最后目标的AOP代理的潜在概念 。在这个示例中,唯一的建议是一个事务解释器用来包装目标方法的事务行为 。这是一种用来在声明性事务功能下使用的基于代理的AOP 。
详解阿里P7架构师是怎么在Spring中实现事务暂停

文章插图
 
Figure 1. An AOP proxy with an advisor chain and a target at the end
例如,一个PetClinic应用的WEB层组件可以执行ServletContext定位来获取Spring WebApplicationContext的引用并且获取受管理的“clinic”BEAN:
清单4:
WebApplicationContext ctx =WebApplicationContexUtils.getWebApplicationContext(servletContext);Clinic clinic = (Clinic) ctx.getBean("clinic);Pet pet = new Pet();pet.setName("my new cat");clinic.storePet(pet);在调用storePet()之前,Spring的事务代理隐式地创建一个事务 。当storePet()调用返回时,事务将提交或回滚 。缺省情况下任何RuntimeException或Error将导致回滚 。实际的提交或回滚可以是可以定义的:Spring的事务属性支持“回滚规则”的概念 。
例如,我们可以可以引入一个强制的PetClinicException并且告诉事务代理在抛出异常时回滚:
清单5:
<prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop><prop key="store*">PROPAGATION_REQUIRED,-PetClinicException</prop>这儿也有一个类似的“提交规则”语法,指示特定的异常将触发一次提交 。
注意上面示例的显式定位引用的方法只是一种访问受Spring管理BEAN的方法的变化,可以用在任何WEB资源如servlet或filter 。在构建基于Spring自身的MVC框架时,BEAN可以直接被注射到WEB控制器中 。当然也支持在如Struts, WebWork, JSF, and Tapestry框架中访问Spring管理BEAN 。详情可以参考Spring的文档 。
详解阿里P7架构师是怎么在Spring中实现事务暂停

文章插图
 
PlatformTransactionManager策略Spring事务支持的核心接口是org.springframework.transaction.PlatformTransactionManager 。所有Spring的事务分离功能都会委托给PlatformTransactionManager(传给相应的TransactionDefinition实例)来做实际的事务执行 。虽然PlatformTransactionManager接口可以直接调用,但通常应用只需要配置一个具体的事务管理器并且通过声明性事务来分离事务 。
Spring提供几种不同的PlatformTransactionManager实现,分为如下两个类别:


推荐阅读