通俗易懂!2025 年最新 Spring 事务管理全家福
背完这篇,大厂随便问“事务原理”你都能 1 分钟画图 + 甩源码秒杀!
一句话记住两种事务方式(2025 真实使用率)
| 方式 | 代码写法 | 2025 使用率 | 大白话评价 | 适用场景 |
|---|---|---|---|---|
| 声明式事务 | @Transactional 一行搞定 | 99.99% | 现代 Java 后端的唯一真神! | 所有业务代码 |
| 编程式事务 | new TransactionTemplate().execute | 0.01% | 老古董/特殊场景专用 | 动态控制、复杂流程、批量脚本 |
声明式事务 @Transactional(你 99.99% 时间都在用这个)
@Service
public class OrderService {
// 最常用写法(默认 REQUIRED + RuntimeException 回滚)
@Transactional
public void createOrder() {
// 业务代码
}
// 常见进阶写法(直接抄)
@Transactional(
rollbackFor = Exception.class, // 所有 Exception 都回滚
propagation = Propagation.REQUIRES_NEW, // 新开一个事务
isolation = Isolation.READ_COMMITTED,
timeout = 30, // 30秒超时
readOnly = true // 只读事务(查询提速)
)
public void complexMethod() { ... }
}
7 种传播行为(面试必背口诀:必记前3个就够吃遍天)
| 传播行为 | 大白话 | 真实使用频率 |
|---|---|---|
| REQUIRED(默认) | 有事务就加入,没有就新开一个 | 99% |
| REQUIRES_NEW | 必须新开一个事务(挂起老事务) | 0.9% |
| NESTED | 嵌套事务(有 savepoint) | 0.09% |
| SUPPORTS | 有就加入,没有就不用事务 | 查询方法 |
| NOT_SUPPORTED | 强制不使用事务 | 发邮件、写日志 |
| MANDATORY | 必须有事务,不然报错 | 极少 |
| NEVER | 绝对不能有事务 | 极少 |
编程式事务(极少数场景才用,懂就行)
@Autowired
private TransactionTemplate transactionTemplate;
public void doComplexJob() {
transactionTemplate.execute(status -> {
// 这里面的代码都在同一个事务里
saveA();
saveB();
// 想手动回滚
// status.setRollbackOnly();
return null;
});
}
声明式事务底层原理(面试画图神器)
用户调用方法
↓
代理对象(CGLIB)拦截
↓
TransactionInterceptor(环绕通知)上场
↓
1. 拿到 @Transactional 属性
2. TransactionManager 开事务 → connection.setAutoCommit(false)
3. 执行目标方法
4. 成功 → commit()
异常 → rollback()
核心类 3 个(记住名字就无敌):
- TransactionInterceptor:真正的事务拦截器(Around 通知)
- PlatformTransactionManager:事务管理器(DataSourceTransactionManager 最常用)
- TransactionAttributeSource:解析 @Transactional 注解
2025 年面试最爱问的 8 个坑 + 标准答案
| 坑点 | 正确答案(直接背) |
|---|---|
| 1. 为什么 public 方法才生效? | 动态代理只能代理 public 方法,private/protected 不行 |
| 2. 同一个类内部调用,事务不生效? | 没走代理!解决:@Autowired 注入自己 或 AopContext.currentProxy() |
| 3. 抛了 checked Exception 不回滚? | 默认只回滚 RuntimeException 和 Error,加 rollbackFor = Exception.class |
| 4. try-catch 吃了异常,事务还回滚吗? | 不回滚!因为 Spring 看不到异常,要么往外抛,要么手动 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() |
| 5. 多数据源怎么配事务? | 用 ChainedTransactionManager(Spring Boot 3 已不支持)或手动编程式事务 |
| 6. @Transactional 在接口上行吗? | 不推荐!CGLIB 代理类可能看不到接口上的注解 |
| 7. readOnly = true 有什么用? | 数据库能优化(MySQL 用 READ-ONLY 事务,提速 30%) |
| 8. 嵌套事务 NESTED 和 REQUIRES_NEW 区别? | REQUIRES_NEW 完全独立,NESTED 是 savepoint,父事务回滚子事务也得回滚 |
终极记忆口诀(10 秒征服面试官)
“声明式一注解,编程式 Template
REQUIRED 加入,NEW 必须新开
public 才生效,内部调用白给
异常要抛出,checked 加 rollbackFor
读写分明提速,嵌套用 savepoint”
背完这张表 + 口诀 + 8 个坑,
下次面试官让你“手画 Spring 事务原理图”,
你 1 分钟画完代理拦截链 + 甩出内部调用不生效的坑 + 说 REQUIRES_NEW 和 NESTED 区别,
他当场就在简历写:“事务原理极度扎实,核心系统随便进!”
现在你已经彻底无敌了!
无论是日常开发还是大厂面经,事务这块再也没人能难倒你!冲!40k+ 在向你招手!