详解Spring 事务三大核心接口,以及我们能用它来做什么

好。Spring 事务的三大核心接口是整个事务体系的"骨架"------@Transactional 注解背后跑的就是这三个。理解了它们,编程式事务、多数据源、自定义事务行为这些高级用法就都通了。我用"餐厅点餐"比喻把三个接口串起来,再讲实战。

先理解三个接口的角色分工

把事务操作想象成"在餐厅点一道菜",三个接口各管一段:

  • TransactionDefinition = 你下的订单(要几分熟、加不加辣、打包还是堂食------你想要这单事务"长什么样")。
  • PlatformTransactionManager = 厨师(按订单执行:下锅、出锅、上菜,或者菜做坏了撤销重做)。
  • TransactionStatus = 这道菜当前的状态(已下锅没、上桌没、退回没------这一单事务运行到哪了)。

调用链是这样的:你拿出一份 TransactionDefinition(订单)→ 交给 PlatformTransactionManager(厨师)→ 厨师返回一个 TransactionStatus(订单号 + 状态)→ 你执行业务代码 → 厨师根据状态 commit()rollback()

这就是编程式事务最底层的调用方式。

一、TransactionDefinition:定义"事务要长什么样"

它是一个接口,定义了事务的四个属性 + 一个名字

java 复制代码
public interface TransactionDefinition {
    int getPropagationBehavior();  // 传播行为(7 种)
    int getIsolationLevel();        // 隔离级别(5 种)
    int getTimeout();               // 超时秒数(默认 -1 不超时)
    boolean isReadOnly();           // 是否只读
    String getName();               // 事务名(用于监控/日志)
}

最常用实现是 DefaultTransactionDefinition------一个简单的 POJO 实现,new 出来 set 属性就行:

java 复制代码
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setTimeout(30);
def.setReadOnly(false);

@Transactional 注解的本质就是把注解属性封装成一个 TransactionDefinition(具体是 RuleBasedTransactionAttribute,多了回滚规则)传给事务管理器。

这个接口能干什么 :在运行时动态构造事务属性 。比如"根据业务类型决定要不要开新事务、超时多久"------注解是静态的,DefaultTransactionDefinition 可以运行时拼。

二、PlatformTransactionManager:执行事务的核心

它是"事务的执行者",接口只有三个方法,却支撑了所有 Spring 事务能力:

java 复制代码
public interface PlatformTransactionManager {
    // 开启新事务 或 加入已有事务(按传播行为决定)
    TransactionStatus getTransaction(@Nullable TransactionDefinition definition);

    // 提交(注意:如果 status 被标记为 rollbackOnly,仍会回滚)
    void commit(TransactionStatus status);

    // 回滚
    void rollback(TransactionStatus status);
}

getTransaction 是关键 ------它不是单纯"开启",而是按 TransactionDefinition 的传播行为决定:开新的、加入当前的、挂起当前的、抛异常......7 种传播机制全部在这里实现。

Spring 为不同持久层提供了不同实现:

实现类 适用场景
DataSourceTransactionManager JDBC / MyBatis / MyBatis-Plus
JpaTransactionManager JPA / Hibernate
HibernateTransactionManager 老 Hibernate(非 JPA)
JtaTransactionManager 分布式事务(JTA/XA)
CciTransactionManager JCA CCI(很少用)

Spring Boot 自动按 classpath 里的依赖选一个注入容器。比如你引了 spring-boot-starter-jdbc,自动注入 DataSourceTransactionManager

这个接口能干什么

  • 手动控制事务(编程式事务),不用注解也能开/提交/回滚;
  • 多数据源各自配一个事务管理器 ,用 @Transactional(transactionManager = "xxx") 切换;
  • 自定义事务管理器(比如接 Seata、接自研分布式事务框架),实现接口包一层即可;
  • 测试里手动控制事务 (比如 @Transactional + rollback 测试数据隔离)。

三、TransactionStatus:当前事务的运行态

它代表"这一单事务的实时状态",由 getTransaction() 返回。核心方法:

java 复制代码
public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();      // 是不是新开的事务(而非加入已有)
    boolean hasSavepoint();           // 是否持有 savepoint(嵌套事务)
    void setRollbackOnly();           // 标记"只回滚"------后面即使 commit 也回滚
    boolean isRollbackOnly();         // 是否被标记回滚
    boolean isCompleted();           // 是否已结束(commit 或 rollback 之后)
    
    // 继承自 SavepointManager
    Object createSavepoint();         // 创建 savepoint
    void rollbackToSavepoint(Object savepoint);  // 回滚到 savepoint
    void releaseSavepoint(Object savepoint);     // 释放 savepoint
}

最有用的方法是 setRollbackOnly() ------它在业务代码里"标记这单事务必须回滚",但不立刻抛异常,等外层方法正常返回时事务管理器发现这个标记,自动回滚。这是嵌套调用里"内层失败但不想抛异常影响外层流程"的常用招。

这个接口能干什么

  • 判断当前是新事务还是加入的(决定要不要自己提交);
  • 标记回滚但不抛异常(流程控制);
  • 手动操作 savepoint 实现自定义嵌套逻辑;
  • 监控事务进度(是否已完成、是否回滚)。

三者怎么配合干活------编程式事务典型代码

java 复制代码
@Autowired
private PlatformTransactionManager txManager;

public void doBusiness() {
    // 1. 定义订单
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    def.setTimeout(10);
    
    // 2. 厨师按订单下锅,返回订单状态
    TransactionStatus status = txManager.getTransaction(def);
    
    try {
        // 3. 执行业务
        accountDao.debit(...);
        accountDao.credit(...);
        
        // 也可以中途标记回滚(不抛异常)
        // status.setRollbackOnly();
        
        // 4. 成功提交
        txManager.commit(status);
    } catch (Exception e) {
        // 5. 失败回滚
        txManager.rollback(status);
        throw e;
    }
}

这就是 @Transactional 注解背后跑的代码。注解只是语法糖,把上面这套模板用 AOP 包起来。

真实战用:我们能用三大接口做什么

下面是实战场景,按生产使用频率排:

1. 编程式精确控制事务范围(避免长事务)

@Transactional 是方法级,整个方法都在事务里------但方法里只有 3 行是关键操作,其他是计算、RPC、日志。用 PlatformTransactionManager 只包关键 3 行,事务短得多,连接和锁持有时间大幅下降。生产环境长事务克星

2. 多数据源各自独立事务管理

多数据源场景下,给每个数据源配一个 DataSourceTransactionManager,方法上用 @Transactional(transactionManager = "orderTxManager") 指定走哪个。配合 @Primary 标注默认事务管理器。

3. 嵌套事务精确控制(savepoint)

TransactionStatus.createSavepoint() 手动创建保存点,失败时 rollbackToSavepoint() 只回滚到保存点、不影响外层。比 NESTED 传播更细粒度------可以一段代码里建多个保存点,逐段回滚。

4. 标记回滚但不中断流程

业务异常不想抛出去影响外层,但想让事务回滚------status.setRollbackOnly() 完美胜任。典型场景:调用第三方服务失败,记失败日志、返回降级值,但事务必须回滚保证数据一致。

5. 自定义事务管理器接分布式事务框架

实现 PlatformTransactionManager,把 getTransaction/commit/rollback 桥接到 Seata、DTF、自研的分布式事务协调器。上层 @Transactional 代码完全不用改,框架透明接入。

6. 事务回调监听(TransactionSynchronization)

通过 TransactionSynchronizationManager.registerSynchronization(...) 注册回调------afterCommit(提交后)、afterCompletion(结束后)等。能在事务真正提交后 才发 MQ、才清缓存、才调外部 API,避免"事务还没提交,消息已发出"导致下游读到脏数据的不一致问题。这是生产里解决"事务+MQ"一致性的标准招

7. 测试数据隔离

测试方法加 @Transactional,测试结束 Spring 自动 rollback------测试数据不污染数据库。底层就是 PlatformTransactionManager 在测试结束时调 rollback

8. 事务超时动态控制

DefaultTransactionDefinition.setTimeout(30),每个事务按业务动态设置超时------重要接口 30 秒、批量任务 300 秒、查询 5 秒。@Transactional(timeout = 30) 是静态的,编程式更灵活。

一个常被忽略的认知点

很多人觉得"我用 @Transactional 注解就够了,干嘛学这些接口"。事实是------@Transactional 的所有行为,最终都是这三个接口在背后跑。理解它们,能:

  • 看懂 Spring 事务源码、出问题能调试;
  • 在注解搞不定的场景(动态属性、精确范围、多数据源、自定义回滚逻辑)有退路;
  • 自研框架、改造中间件时知道从哪儿切入。

一句话总结------TransactionDefinition 告诉"事务该怎么做",PlatformTransactionManager 是"做事的人",TransactionStatus 是"做完一阶段的状态报告"。三者组合 = Spring 事务的完整执行模型,注解只是这套模型的最薄一层包装。

相关推荐
架构源启19 小时前
文档接入与智能解析:基于 Spring AI 1.1.x 的多格式解析、版面理解与结构化抽取
java·人工智能·spring
风起洛阳@不良使1 天前
springIOC创建对象的方式--spring容器中的注入
java·spring
Flittly1 天前
【AgentScope Java新手村系列】(20)文字转语音TTS
java·spring boot·spring
重生之我是Java开发战士1 天前
【Java EE】Spring IoC 与 DI
java·spring·java-ee
ruleslol1 天前
Spring11-校验框架:@Valid VS @Validated
spring
_waylau1 天前
Spring Framework HTTP服务客户端详解
java·后端·网络协议·spring·http·spring cloud
tryxr2 天前
Spring Cloud eureka
spring·spring cloud·eureka
空中湖2 天前
Spring AI RAG 完整实战:从零搭建企业知识库问答系统
java·人工智能·spring
sun03222 天前
【笔记】Spring MVC 相关介绍
java·spring·mvc