• admin
  • 274
  • 2025-06-28 23:37:48

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

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

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

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

Spring 事务的两种实现方式:

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

📌 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 默认包含事务管理功能:

org.springframework.boot

spring-boot-starter-data-jpa

② 在 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 配置如下:

④ 测试事务

@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 注解的执行流程

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

源码解析

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 处理事务。

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