详解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 事务的完整执行模型,注解只是这套模型的最薄一层包装。

相关推荐
BUG指挥官15 小时前
Sa-Token和Spring Security对比
java·后端·spring
geminigoth15 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
xbgRS18 小时前
spring整合mybaits
java·spring·mybatis
ruleslol18 小时前
静态依赖注入 VS 动态依赖查询
spring
墨雨晨曦8821 小时前
Spring AI总结
java·人工智能·spring
用户3126874877201 天前
Spring Boot 异常处理到底怎么玩的?从 DispatcherServlet 到全局兜底的全链路拆解
spring
不才不才不不才1 天前
Spring 源码系列(17): HandlerMapping 与 HandlerAdapter 两大体系
java·后端·spring
(轻舟已过万重山)1 天前
第40章 Spring AI 实战:企业级 AI 应用架构
人工智能·spring·架构
堕落年代2 天前
Ollama CPU 推理大提示词优化实测报告(细致化数据版)
java·后端·spring
cfm_29142 天前
基于OAuth2.0实现微服务SSO单点登录
后端·spring·微服务·架构