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
默认包含事务管理功能:
<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
注解的执行流程
- 代理拦截: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
处理事务。
🚀 你学会了吗?如果觉得有帮助,记得点赞+收藏!欢迎留言交流! 😊
微信扫一扫:分享
微信里点“发现”,扫一下
二维码便可将本文分享至朋友圈。