Spring 事务管理全解析:原理、源码与实战

Scroll Down

Spring 事务管理全解析:原理、源码与实战

事务(Transaction) 是保证数据一致性的重要机制,Spring 通过 声明式事务编程式事务 提供强大的事务管理能力。本篇文章将深入剖析 Spring 事务的底层原理、传播机制、源码解析,并通过代码实战讲解如何正确使用 Spring 事务。


📌 1. 什么是事务?(What)

事务是数据库操作的最小执行单元,必须具备 ACID(原子性、一致性、隔离性、持久性)特性。

Spring 事务的两种实现方式:

  1. 声明式事务(Declarative Transaction)(推荐):使用 @Transactional 注解,无需手动管理事务。
  2. 编程式事务(Programmatic Transaction):手动管理 TransactionTemplatePlatformTransactionManager

📌 2. 为什么需要 Spring 事务?(Why)

❌ 问题:没有事务时可能导致数据不一致

假设 UserService 有一个 transfer() 方法,执行两步操作:

public void transfer(String from, String to, double amount) {
    accountDao.debit(from, amount);  // 从账户 A 扣款
    int error = 1 / 0;  // 模拟异常
    accountDao.credit(to, amount);  // 向账户 B 存款
}

结果:
💥 accountDao.debit() 执行成功,但 accountDao.credit() 失败,导致 钱扣了但没到账!

✅ 解决方案:使用事务管理,保证数据一致性

@Transactional
public void transfer(String from, String to, double amount) {
    accountDao.debit(from, amount);
    int error = 1 / 0;  // 模拟异常
    accountDao.credit(to, amount);
}

结果:
❌ 发生异常,事务回滚,accountDao.debit() 的操作被撤销,避免数据错误。


📌 3. 如何使用 Spring 事务?(How)

✅ 方式一:基于 @Transactional 的声明式事务(推荐)

① 添加 Spring 事务依赖

如果是 Spring Boot 项目,spring-boot-starter-data-jpa 默认包含事务管理功能:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

② 在 Service 层开启事务

@Service
public class AccountService {
    @Autowired
    private AccountDao accountDao;

    @Transactional
    public void transfer(String from, String to, double amount) {
        accountDao.debit(from, amount);
        int error = 1 / 0;  // 模拟异常
        accountDao.credit(to, amount);
    }
}

③ 配置 @EnableTransactionManagement

如果 Spring Boot 已自动配置,无需额外配置。Spring XML 配置如下:

<tx:annotation-driven transaction-manager="transactionManager"/>

④ 测试事务

@SpringBootTest
@RunWith(SpringRunner.class)
public class TransactionTest {
    @Autowired
    private AccountService accountService;

    @Test
    public void testTransaction() {
        accountService.transfer("Alice", "Bob", 100);
    }
}

🔥 运行结果:

  • 如果 @Transactional 生效,Alice 账户扣款后发生异常,事务回滚,数据不变。
  • 如果没有事务管理,Alice 账户扣款后异常,Bob 账户不会收到钱,导致数据错误。

✅ 方式二:编程式事务管理

如果想手动控制事务,可使用 TransactionTemplate

@Service
public class AccountService {
    @Autowired
    private TransactionTemplate transactionTemplate;

    public void transfer(String from, String to, double amount) {
        transactionTemplate.execute(status -> {
            accountDao.debit(from, amount);
            int error = 1 / 0;  // 模拟异常
            accountDao.credit(to, amount);
            return null;
        });
    }
}

编程式事务适用于:需要在代码中动态管理事务的复杂场景,例如嵌套事务、动态回滚等。


📌 4. 事务传播机制(Propagation)

Spring 事务支持 7 种传播行为(Propagation),用于控制嵌套事务的执行方式。

传播类型 描述 适用场景
REQUIRED(默认) 如果当前没有事务,则新建一个;如果已有事务,则加入 适用于大多数业务场景
REQUIRES_NEW 总是新建一个事务,当前事务挂起 适用于事务隔离的情况
NESTED 如果当前存在事务,则创建子事务 适用于部分回滚
SUPPORTS 如果当前有事务,则加入;没有事务,则以非事务方式运行 适用于事务可选的场景
NOT_SUPPORTED 以非事务方式运行,挂起当前事务 适用于不需要事务的操作
NEVER 以非事务方式运行,若当前有事务则抛异常 适用于强制无事务的情况
MANDATORY 必须在已有事务中运行,否则抛异常 适用于强制要求事务

示例:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA() {
    methodB(); // 执行时创建新事务,methodB 不会影响 methodA
}

@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
    // 加入 methodA 的事务,methodB 出错会导致 methodA 也回滚
}

📌 5. Spring 事务底层原理

🔥 @Transactional 注解的执行流程

  1. 代理拦截:Spring AOP 生成代理对象(JDK 动态代理或 CGLIB)。
  2. 事务管理器TransactionInterceptor 拦截方法调用,委托 TransactionManager 处理事务。
  3. 数据库连接:Spring 事务使用 DataSourceTransactionManager 管理数据库连接。
  4. 事务提交或回滚:方法执行成功,提交事务;发生异常,回滚事务。

源码解析

Spring AOP 代理执行事务:

public Object invoke(MethodInvocation invocation) throws Throwable {
    TransactionInfo txInfo = createTransactionIfNecessary();
    try {
        Object retVal = invocation.proceed();
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } catch (Throwable ex) {
        rollbackTransaction(txInfo, ex);
        throw ex;
    }
}

事务管理器 DataSourceTransactionManager

public void commit(TransactionStatus status) {
    if (!status.isCompleted()) {
        doCommit(status);
    }
}

事务回滚

public void rollback(TransactionStatus status) {
    if (!status.isCompleted()) {
        doRollback(status);
    }
}

📌 6. 总结

声明式事务 @Transactional 是最推荐的方式,简洁高效。
Spring 事务传播机制 适用于复杂业务场景。
事务底层基于 AOP 代理,拦截方法执行,委托 TransactionManager 处理事务。

🚀 你学会了吗?如果觉得有帮助,记得点赞+收藏!欢迎留言交流! 😊