核心思想

Spring事务管理的核心思想是:将复杂多变的事务管理能力抽象成一个统一的平台,让开发者可以专注于业务逻辑,而不必处理不同数据源(如JDBC, JPA, Hibernate)各自的事务API。

它实现了声明式事务(Declarative Transaction),即通过配置(XML或注解)来定义事务规则(传播行为、隔离级别等),而无需在业务代码中编写繁琐的事务控制代码(如beginTransaction(), commit(), rollback())。Spring在运行时自动将这些规则应用到方法上。


关键组件

要实现这个抽象,Spring主要依赖以下几个核心接口和组件:

  1. PlatformTransactionManager (平台事务管理器)

    • 这是Spring事务抽象的核心接口。所有的事务策略(无论是JDBC、JPA还是JTA)都通过这个接口的实现类来完成。
    • 它定义了事务操作的基本方法:getTransaction(), commit(), rollback()
    • 常见实现类:
      • DataSourceTransactionManager: 用于单一的JDBC数据源(使用java.sql.Connection来实现事务)。
      • JpaTransactionManager: 用于JPA(底层通常还是Hibernate)。
      • HibernateTransactionManager: 用于原生Hibernate。
      • JtaTransactionManager: 用于分布式事务(JTA),可以管理多个数据源的事务。
  2. 事务定义 (TransactionDefinition)

    • 它定义了事务的属性,也就是我们常配置的那些东西:
      • 传播行为 (Propagation Behavior): 例如,REQUIRED(如果当前没有事务,就新建一个;如果有,就加入)、REQUIRES_NEW(新建一个事务,挂起当前事务)等。
      • 隔离级别 (Isolation Level): 例如,READ_COMMITTED(读已提交)、REPEATABLE_READ(可重复读)等。
      • 超时时间 (Timeout)
      • 是否只读 (Read-Only)
    • 我们使用的 @Transactional 注解的属性,最终就会被解析成一个 TransactionDefinition 对象。
  3. 事务状态 (TransactionStatus)

    • 它代表了事务的当前状态,比如事务是否是新创建的、是否已完成、是否有回滚标记等。PlatformTransactionManagergetTransaction() 方法返回的就是一个 TransactionStatus 对象。

实现原理:AOP + 动态代理

Spring事务的声明式实现,其底层技术是 AOP(面向切面编程)动态代理

简单来说,Spring在运行时为目标对象(你的Service类)创建一个代理对象。当你调用一个被@Transactional标记的方法时,实际上是在调用代理对象的方法。这个代理方法会在你的业务方法执行“之前”和“之后”,由Spring事务拦截器 (TransactionInterceptor) 自动加入事务管理的代码。

这个过程可以分解为以下几个步骤:

  1. 解析和注册:

    • 当Spring容器启动时,它会解析所有Bean的定义。
    • 如果发现某个Bean的方法上有 @Transactional 注解(或者XML配置了事务通知),Spring会意识到这个Bean需要被事务管理。
  2. 创建代理:

    • Spring使用AOP机制(默认是CGLIB动态代理,如果类实现了接口,也可以用JDK动态代理)为这个Bean创建一个代理对象(Proxy),并将 TransactionInterceptor(事务拦截器)作为一个“通知(Advice)”织入到这个代理对象中。
    • 最终,注入到其他Bean(如Controller)中的,实际上是这个代理对象,而不是原始的目标对象。
  3. 方法调用流程(核心):
    当你通过代理对象调用一个事务方法时(例如 userService.createUser()),调用链如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // 伪代码,展示代理对象的执行逻辑
    public class UserServiceProxy extends UserService {
    private TransactionInterceptor txInterceptor;

    @Override
    public void createUser() {
    // 1. 前置处理:开启事务
    TransactionStatus status = txInterceptor.getTransactionManager().getTransaction(txInterceptor.getTransactionAttributes());

    try {
    // 2. 回调:执行目标对象的真实业务方法
    super.createUser(); // 你的业务代码在这里执行

    // 3. 后置处理:如果没有异常,提交事务
    txInterceptor.getTransactionManager().commit(status);
    } catch (Exception e) {
    // 4. 异常处理:根据配置的异常类型决定回滚还是提交
    if (txInterceptor.rollbackOn(e)) {
    txInterceptor.getTransactionManager().rollback(status);
    } else {
    txInterceptor.getTransactionManager().commit(status);
    }
    throw e;
    }
    }
    }
    • TransactionInterceptor 是这个流程的核心协调者。它会:
      a. 根据 @Transactional 的配置,创建一个 TransactionDefinition
      b. 调用 PlatformTransactionManager,根据定义获取事务(getTransaction),并返回一个 TransactionStatus
      c. 执行业务方法( invocation.proceedWithInvocation())。
      d. 业务方法成功返回,调用 commit()
      e. 业务方法抛出异常,根据规则判断是否需要进行 rollback()

工作流程总结

  1. 配置事务管理器:在Spring配置中定义一个 PlatformTransactionManager Bean(如 DataSourceTransactionManager)。
  2. 启用事务管理:使用 @EnableTransactionManagement(Java Config)或 <tx:annotation-driven/>(XML)来启用基于注解的事务管理。
  3. 标记事务方法:在Service层的类或方法上使用 @Transactional 注解。
  4. Spring容器启动:解析注解,为被标记的Bean创建代理对象,并织入事务拦截逻辑。
  5. 方法调用
    • Controller调用 userService.createUser(),实际调用的是代理对象的方法。
    • 代理对象委托给 TransactionInterceptor
    • 拦截器开启事务 -> 调用原始业务方法 -> 根据成功或异常提交或回滚事务。

重要提醒

  • 自调用问题:在同一个类中,一个非事务方法A调用另一个事务方法B,事务会失效。因为A调用的是this.B(),而不是代理对象的proxy.B(),所以事务拦截逻辑不会被执行。必须通过代理对象调用才行。
  • 异常回滚:默认只在抛出运行时异常RuntimeException 及其子类)和 Error 时回滚。受检异常(Checked Exception) 不会导致回滚。可以通过 @Transactional(rollbackFor = Exception.class) 来改变默认行为。
  • 选择正确的管理器:确保你使用的 PlatformTransactionManager 与你的持久化技术(JDBC, JPA, Hibernate)匹配。