事务(Transaction) 是保证数据一致性的重要机制,Spring 通过 声明式事务 和 编程式事务 提供强大的事务管理能力。本篇文章将深入剖析 Spring 事务的底层原理、传播机制、源码解析,并通过代码实战讲解如何正确使用 Spring 事务。
事务是数据库操作的最小执行单元,必须具备 ACID(原子性、一致性、隔离性、持久性)特性。
Spring 事务的两种实现方式:
@Transactional
注解,无需手动管理事务。TransactionTemplate
或 PlatformTransactionManager
。假设 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()
的操作被撤销,避免数据错误。
@Transactional
的声明式事务(推荐)如果是 Spring Boot 项目,spring-boot-starter-data-jpa
默认包含事务管理功能:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
@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;
});
}
}
编程式事务适用于:需要在代码中动态管理事务的复杂场景,例如嵌套事务、动态回滚等。
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 也回滚
}
@Transactional
注解的执行流程TransactionInterceptor
拦截方法调用,委托 TransactionManager
处理事务。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);
}
}
✅ 声明式事务 @Transactional
是最推荐的方式,简洁高效。
✅ Spring 事务传播机制 适用于复杂业务场景。
✅ 事务底层基于 AOP 代理,拦截方法执行,委托 TransactionManager
处理事务。
你学会了吗?如果觉得有帮助,记得点赞+收藏!欢迎留言交流!