对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

Spring 框架事务支持模型的优势

传统上,Java EE 应用程序开发人员在事务管理方面只有两种选择:全局事务或本地事务,而这两者都存在明显的局限性。接下来的两节将分别回顾全局事务和本地事务管理,随后讨论 Spring 框架的事务管理支持如何解决全局和本地事务模型的局限性。spring-doc.cadn.net.cn

全局事务

全局事务允许您操作多个事务性资源,通常包括关系型数据库和消息队列。应用服务器通过 JTA(Java Transaction API)来管理全局事务,而 JTA 是一个繁琐的 API(部分原因在于其异常模型)。此外,JTA 的 UserTransaction 通常需要从 JNDI 获取,这意味着您必须使用 JNDI 才能使用 JTA。全局事务的使用限制了应用程序代码的潜在重用性,因为 JTA 通常仅在应用服务器环境中可用。spring-doc.cadn.net.cn

过去,使用全局事务的首选方式是通过 EJB CMT(容器管理事务)。CMT 是一种声明式事务管理形式(区别于编程式事务管理)。EJB CMT 消除了与事务相关的 JNDI 查找需求,尽管使用 EJB 本身仍需要使用 JNDI。它消除了大部分(但并非全部)编写 Java 代码来控制事务的需求。然而,其显著缺点在于 CMT 与 JTA 和应用服务器环境紧密绑定。此外,只有在选择使用 EJB 实现业务逻辑(或至少通过一个事务性的 EJB 外观层)时,CMT 才可用。鉴于 EJB 整体上存在诸多弊端,这一方案并不具吸引力,尤其是在当前已有极具竞争力的声明式事务管理替代方案的情况下。spring-doc.cadn.net.cn

本地事务

本地事务是特定于资源的,例如与 JDBC 连接关联的事务。本地事务可能更易于使用,但有一个明显的缺点:它们无法跨多个事务性资源工作。例如,使用 JDBC 连接管理事务的代码无法在全局 JTA 事务中运行。由于应用服务器不参与事务管理,因此无法帮助确保跨多个资源的一致性。(值得注意的是,大多数应用程序仅使用单一事务资源。)另一个缺点是,本地事务会对编程模型造成侵入性影响。spring-doc.cadn.net.cn

Spring Framework 的一致编程模型

Spring 解决了全局事务和本地事务的缺点。它允许应用程序开发人员在任何环境中使用一致的编程模型。 你只需编写一次代码,即可在不同环境中受益于不同的事务管理策略。Spring 框架同时提供了声明式和编程式事务管理。 大多数用户更倾向于声明式事务管理,我们在大多数情况下也推荐使用这种方式。spring-doc.cadn.net.cn

使用编程式事务管理时,开发人员直接使用 Spring Framework 的事务抽象层,该抽象层可以在任何底层事务基础设施之上运行。 而在更推荐的声明式模型中,开发人员通常只需编写很少甚至无需编写与事务管理相关的代码,因此不依赖于 Spring Framework 的事务 API 或任何其他事务 API。spring-doc.cadn.net.cn

您需要应用服务器来进行事务管理吗?

Spring框架的事务管理支持改变了传统的企业Java应用需要应用服务器的规定。spring-doc.cadn.net.cn

特别是,你并不需要仅仅为了通过 EJB 实现声明式事务而使用应用服务器。事实上,即使你的应用服务器具备强大的 JTA 功能,你仍可能认为 Spring 框架的声明式事务提供了比 EJB CMT 更强大的能力以及更高效的编程模型。spring-doc.cadn.net.cn

通常,只有当您的应用程序需要跨多个资源处理事务时,才需要应用服务器的 JTA(Java Transaction API)功能,而许多应用程序并不需要这一要求。许多高端应用程序转而使用单一、高度可扩展的数据库(例如 Oracle RAC)。独立的事务管理器(例如 Atomikos Transactions )是另一种选择。当然,您可能还需要应用服务器的其他功能,例如 Java 消息服务(JMS)和 Jakarta EE 连接器架构(JCA)。spring-doc.cadn.net.cn

Spring 框架让你可以自主选择何时将应用程序扩展到完整的应用服务器。过去,除了使用 EJB CMT 或 JTA 之外,唯一的选择就是编写使用本地事务(例如 JDBC 连接上的事务)的代码,而一旦需要让这些代码在全局的、容器管理的事务中运行时,就得进行大量重构。而借助 Spring 框架,你只需更改配置文件中的部分 bean 定义即可(而无需修改你的代码)。spring-doc.cadn.net.cn