声明式事务管理
大多数Spring框架用户选择声明式事务管理。这种选项对应用程序代码的影响最小,因此,最符合非侵入式轻量级容器的理念。
Spring框架的声明式事务管理是通过Spring的面向切面编程(AOP)实现的。然而,由于事务相关的代码是随Spring框架一起提供的,并且可以以样板化的方式使用,因此通常不需要理解AOP的概念就能有效地利用这些代码。
Spring框架的声明式事务管理与EJB CMT类似,因为你可以在单个方法层面指定事务行为(或不进行事务处理)。如有必要,你可以在事务上下文中调用setRollbackOnly()方法。这两种事务管理方式之间的区别如下:
-
与依赖于JTA的EJB CMT不同,Spring框架的声明式事务管理可以在任何环境中使用。通过调整配置文件,它既可以支持JTA事务,也可以使用JDBC、JPA或Hibernate进行本地事务管理。
-
你可以将Spring框架的声明式事务管理应用到任何类上,而不仅仅是像EJB这样的特殊类。
-
Spring框架提供了声明式的回滚规则,这是EJB所不具备的功能。Spring框架同时支持编程式和声明式的回滚规则实现方式。
-
Spring框架允许你通过AOP来定制事务行为。例如,你可以在事务回滚时插入自定义逻辑。此外,你还可以添加任意的事务相关建议(advice)。而在EJB CMT中,除了使用
setRollbackOnly()方法外,你无法影响容器的事务管理。 -
Spring框架不支持像高端应用服务器那样的远程调用间的事务上下文传递功能。如果需要这一功能,我们建议使用EJB。不过,在使用该功能之前请仔细考虑,因为通常情况下,人们并不希望事务跨越远程调用范围。
回滚规则的概念非常重要。它们允许你指定哪些异常(以及可抛出对象)应该触发自动回滚。你可以通过配置来明确指定这些规则,而无需在Java代码中实现。因此,虽然你仍然可以在TransactionStatus对象上调用setRollbackOnly()来回滚当前事务,但通常情况下,你可以规定MyApplicationException这种异常必须总是导致回滚。这种做法的显著优势在于:业务对象并不依赖于事务基础设施。例如,它们通常不需要导入Spring的事务API或其他Spring API。
尽管EJB容器在系统异常(通常是运行时异常)发生时会自动回滚事务,但EJB CMT在应用程序异常(即除java.rmi.RemoteException之外的受检异常)发生时并不会自动回滚事务。虽然Spring对于声明式事务管理的默认行为遵循EJB的约定(仅对不受检异常进行自动回滚),但通常情况下自定义这一行为会更为有用。
部分总结
📄️ 理解Spring框架的声明式事务实现
仅仅告诉你在类上添加 @Transactional 注解,在配置中加入 @EnableTransactionManagement,然后期望你能够理解这一切是如何工作的,这是不够的。为了提供更深入的理解,本节将在与事务相关问题的背景下,解释 Spring Framework 声明式事务基础设施的内部工作原理。
📄️ 声明式事务实现的示例
考虑以下接口及其相应的实现。在这个示例中,使用Foo和Bar类作为占位符,这样你就可以专注于事务的使用,而无需关注特定的领域模型。对于这个示例来说,DefaultFooService类在每个实现方法的主体中抛出UnsupportedOperationException实例这一事实是合适的。这种行为让你能够看到事务的创建,然后由于UnsupportedOperationException实例的存在而回滚事务。以下列表显示了FooService接口:
📄️ 回滚声明式事务
前一节概述了如何在应用程序中以声明式的方式为类(通常是服务层类)指定事务设置的基本方法。本节将描述如何通过XML配置以简单、声明式的方式来控制事务的回滚。有关使用@Transactional注解以声明式方式控制回滚语义的详细信息,请参阅@Transactional设置。
📄️ 为不同的Bean配置不同的事务语义
想象这样一种情况:你有多个服务层对象,而你想对每一个对象应用完全不同的事务配置。你可以通过定义具有不同切点和advice-ref属性值的aop:advisor/元素来实现这一点。
📄️ tx:advice/ 设置
本节总结了您可以使用tx:advice/标签指定的各种事务设置。默认的tx:advice/设置如下:
📄️ 使用 @Transactional
除了基于XML的声明式事务配置方法外,您还可以使用基于注解的方法。直接在Java源代码中声明事务语义,可以将这些声明与受影响的代码更紧密地结合在一起。这样几乎不会产生不必要的耦合风险,因为原本就打算用于事务处理的代码,几乎总是以这种方式部署的。
📄️ 事务传播
本节描述了Spring中事务传播的一些语义规则。需要注意的是,本节并非对事务传播的完整介绍,而是详细说明了Spring中关于事务传播的某些具体规则。
📄️ 交易操作咨询
假设你希望同时运行事务性操作和一些基本的性能分析(profiling)功能。在tx:annotation-driven/的上下文中,你该如何实现这一点呢?
📄️ 在AspectJ中使用@Transactional
您也可以通过AspectJ切面在Spring容器之外使用Spring框架的@Transactional支持。为此,首先需要用@Transactional注解标注您的类(以及可选的类方法),然后将您的应用程序与spring-aspects.jar文件中定义的org.springframework.transaction.aspectj.AnnotationTransactionAspect进行链接(编织)。您还需要配置该切面以使用事务管理器。您可以利用Spring框架的IoC容器来处理切面的依赖注入。配置事务管理切面最简单的方法是使用tx:annotation-driven/元素,并将mode属性指定为“aspectj”,具体方法如“使用@Transactional”一节所述。由于我们在这里关注的是在Spring容器之外运行的应用程序,因此我们将向您展示如何通过编程方式来实现这一点。