简介
Annotation还是XML的配置方式一直是Java world争论的焦点; 声明式事务管理(Declarative Transaction Management)是现在用的最多的一种事务管理方式。Spring同时提供了Annotation和XML配置方式的声明式事务管理。本文主要讨论这两种方式的各自特点,以及如何选择适当的声明式事务配置方式
声明式事务
自从EJB提出了声明式事务管理的概念,声明式事务管理就成为事务管理的最佳选择。在Spring出来之前,使用声明式事务需要使用符合J2EE规范的应用服务器,例如Weblogic, Websphere等。Spring出来以后,可以通过 AOP非常优雅的实现了声明式事务,而不必需要应用服务器的支持,这也是很多人选择使用Spring的原因。
Spring提供了Annotation风格和XML风格的声明式事务管理。下文将分别讨论这两种方式的优缺点。
XML风格
从Sping1.x就开始支持的风格,在spirng2.0中同时使用AspectJ风格的AOP更加简化了这种风格的配置。这种方式也是目前使用最多的一种方式。
<beans> <aop:config> <aop:pointcut id="defaultServiceOperation" expression="execution(* x.y.service.*Service.*(..))"/> <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/> <aop:pointcut id="noTxServiceOperation" expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/> <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/> </aop:config> <!-- this bean will be transactional (c.f. the 'defaultServiceOperation' pointcut) --> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- this bean will also be transactional, but with totally different transctional settings --> <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/> <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> <!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... --> </beans>
优点: 简单明了,事务的配置在一个配置文件中体现,事务切面比较清楚。更改事务定义,不需要修改源代码。
缺点:不够灵活,对单个方法的事务管理不好配置。例如有如下类和方法
public class A {
public m() {
//需要事务
a();
//不需要事务,操作时间比较长。
b();
}
//需要事务定义
public n() {
…
}
}
Method a,而method b不需要事务。如果method b需要运行的时间比较长,这时:
- 在method m上声明事务定义,那么method m很容易事务超时。当然你可以将transaction time out设的时间长一点,但这显然不是最好的解决办法。
- 不在method m上声明事务定义,只在a上声明事务,但是class A的method n又需要事务定义,这时spring xml方式的声明式事务就无法定义了。只能将method m从class A中移除,放入一个单独的不需要事务定义的类中。这就有可能将一些语义上内聚的方法拆分到不同的类中。
Annotation风格
Spring2.0开始支持Annotation风格的声明式事务。可以在类或者方法级别声明事务,具体可参考spring手册
public class A {
public m() {
a();
//不需要事务,操作时间比较长
b();
}
@Transactional
public n() {
…
}
}
优点: 比较灵活,在一个类中,我可以选择指定哪些方法需要事务。在上一节的例子中,我们就可以在方法 n上声明事务, 而方法m不用声明事务,不用新建一个类。
缺点:事务定义分散在源代码中,没有一个统一的事务切面视图。修改事务定义,需要修改源代码。
Summary
在选择XML还是Annotation的问题上,java社区还是有很多争论,Annotation风格越来越受到重视。实际应用中,是一个case by case的问题。在经典的3层体系结构(presentation,service,persistent)中,现在通常会把事务边界定义在业务层,而选择以哪种方式声明事务可以参考以下几点建议:
- 如果service层的方法绝大部分都是数据库操作,我们可以使用XML风格在service层声明事务边界。
- 如果service层的方法除了数据库操作外,还有很多耗时的业务方法(例如XML风格一节的例子),那么就可以采用Annotation风格。
- 也可以将XML风格和Annotation风格结合起来一起使用。这是我推荐使用的,只使用两种风格的优点,而避免了它们的缺点。