人人都会AI编程

6.1 Spring 事务抽象:PlatformTransactionManager 统一接口

更新时间:2026-07-11

在企业应用中,事务管理是不可或缺的保障机制,确保一组数据操作要么全部成功提交,要么全部回滚到操作前的状态。Java 生态中存在多种事务实现方式:JDBC 事务、JTA 分布式事务、Hibernate 事务、JPA 事务等,各自的 API 各不相同。如果开发者在业务代码中直接调用这些不同的事务 API,一旦需要切换数据访问技术,事务代码就必须全部重写。

Spring 通过 PlatformTransactionManager 接口将所有事务策略统一到同一个编程模型中,无论底层使用的是 JDBC、JTA 还是 Hibernate,上层代码看到的都是同一套抽象。

6.1.1 统一接口的核心设计

PlatformTransactionManager 位于 spring-tx 模块中,是 Spring 事务抽象的基石。它只定义了三个核心方法:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) 
        throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

这三个方法对应事务执行的三个关键步骤:获取事务、提交事务、回滚事务。开发者(或 Spring 框架本身)通过调用这些方法来管理事务,完全不需要知道底层是 JDBC 还是 Hibernate。交互过程中使用的 TransactionDefinitionTransactionStatus 也都是抽象接口,进一步屏蔽了实现细节。

  • TransactionDefinition:描述事务的元数据,包括传播行为、隔离级别、超时时间、是否只读等。例如,当调用 getTransaction 时,Spring 会根据这个定义决定是创建一个新事务,还是加入已存在的事务。
  • TransactionStatus:表示当前事务的运行状态,可以检查是否为新事务、是否已完成、是否要求回滚等,并可通过 setRollbackOnly() 强制标记当前事务只能回滚,即使没有遇到异常。

6.1.2 具体实现类:一套接口,多种实现

PlatformTransactionManager 之下,针对不同数据访问技术有一系列具体实现。选择哪个实现类,取决于项目使用的持久层框架。以下是几种最常用的实现:

1. DataSourceTransactionManager(JDBC 或 MyBatis)

如果你在代码中直接使用 JdbcTemplate,或者使用 MyBatis(底层仍是 JDBC 连接),则事务管理需要围绕 DataSource 进行。DataSourceTransactionManager 通过持有 DataSource,在事务开始时从连接池获取一个连接,并将此连接绑定到当前线程。同一个事务内的所有数据库操作共享同一个数据库连接,保证了事务的原子性。

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

真实项目中,Spring Boot 在引入了 spring-boot-starter-jdbcmybatis-spring-boot-starter 后,会自动检测到 DataSource,并为我们创建 DataSourceTransactionManager 类型的 Bean,除非我们显式指定其他类型的事务管理器。

2. JpaTransactionManager(JPA)

如果项目通过 JPA(例如 Hibernate)操作数据库,应使用 JpaTransactionManager。它不仅能管理 EntityManager 的生命周期,还能将 JPA 事务与 Spring 的事务管理融为一体,支持在同一事务内混合使用 JPA 和 JDBC 操作(前提是共享同一个 DataSource)。

@Bean
public PlatformTransactionManager transactionManager(
        EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
}

3. JtaTransactionManager(分布式事务)

当应用需要跨多个数据源、消息队列等资源进行全局事务时(例如在多个数据库之间保持数据一致),就需要借助 JTA(Java Transaction API)提供的分布式事务能力。JtaTransactionManager 委托给应用服务器的 JTA 协调器(如 Atomikos、Bitronix 或 WebLogic 等)来管理事务,Spring 本身不做分布式事务的引擎,只由该实现进行适配。

6.1.3 统一抽象在声明式事务中的运作方式

尽管 PlatformTransactionManager 的 API 简洁明了,但在日常开发中我们几乎不会直接调用它们,而是使用 @Transactional 注解声明事务。当一个方法标注了 @Transactional,Spring 在启动时会通过 AOP 为该 Bean 创建一个代理对象。当代理对象拦截到方法调用时,执行流程大致如下:

  1. 读取方法或类上的事务属性(传播行为、隔离级别等),构建 TransactionDefinition 实例。
  2. 调用 PlatformTransactionManager.getTransaction(definition),根据当前事务上下文和定义,处理事务传播(如有则加入,无则新建等)。此时,如果事务被创建,底层连接会被设置为非自动提交模式,并绑定到当前线程。
  3. 执行真正的业务方法(targetMethod.invoke())。业务代码可以像平常一样使用 JdbcTemplateEntityManager,因为它们都共享同一个线程绑定的数据库连接。
  4. 若业务方法正常返回,AOP 拦截器调用 PlatformTransactionManager.commit(status) 提交事务。
  5. 若业务方法抛出特定异常(默认是未被捕获的 RuntimeExceptionError),拦截器调用 PlatformTransactionManager.rollback(status) 进行回滚。

整个过程,业务代码中完全没有出现任何事务 API,只看到了一个 @Transactional 注解,真正的脏活累活全部由 PlatformTransactionManager 与 AOP 配合完成。

6.1.4 真实项目中的事务管理器配置

在 Spring Boot 项目中,事务管理器几乎不需要手动配置。只要在类路径下存在相应的依赖,Spring Boot 的自动配置就会自动创建合适的事务管理器 Bean。

但有时一个应用需要连接多个数据库。此时需要显式定义多个事务管理器,并指定哪一个作为默认或按限定的名称注入:

@Configuration
public class MultiDataSourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.order")
    public DataSource orderDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("app.datasource.report")
    public DataSource reportDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public PlatformTransactionManager orderTransactionManager(
            @Qualifier("orderDataSource") DataSource ds) {
        return new DataSourceTransactionManager(ds);
    }

    @Bean
    public PlatformTransactionManager reportTransactionManager(
            @Qualifier("reportDataSource") DataSource ds) {
        return new DataSourceTransactionManager(ds);
    }
}

使用时,如果需要在非默认的事务管理器上开启事务,可以指定 @TransactionaltransactionManager 属性:

@Transactional(transactionManager = "reportTransactionManager")
public void generateReport() {
    // 操作报表数据库...
}

6.1.5 理解事务抽象带来的价值

PlatformTransactionManager 的统一接口设计,让事务管理从具体的数据库操作中解耦。业务方法只需考虑正确完成业务逻辑,事务的开启、提交、回滚由 Spring 在幕后完成。开发团队可以在不同项目、不同持久层技术栈之间复用相同的编程模型,甚至可以在单元测试中通过配置一个简单的 DataSourceTransactionManager 替代重量级的 JTA 事务,从而在本地快速测试事务行为。

这种一致性是 Spring 最被认可的工程价值之一:用极简的接口,隐藏了底层事务机制的复杂度,并且与容器的其他能力(AOP、自动配置、资源同步)无缝集成,让开发者可以信赖框架在关键时刻做出正确的提交与回滚决定。