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 默认包含事务管理功能:
② 在 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 处理事务。
🚀 你学会了吗?如果觉得有帮助,记得点赞+收藏!欢迎留言交流! 😊