前言:Spring的事务管理堪称开发中的"大杀器",但也是新手踩坑重灾区!明明配置了事务,数据却该回滚不回滚?今天咱们就把Spring AOP事务控制的底裤扒干净,从XML配置到注解开发,再到最容易踩的坑,一次性讲透!
一、先搞懂:AOP和事务到底啥关系?
在聊具体配置前,先给新手小伙伴打个比方:
-
事务(Advice/增强):就是你想干的"正事"------要么成功提交,要么失败回滚
-
切点(Pointcut):就是你想给哪些方法加事务(比如所有Service层的方法)
-
切面(Aspect):把事务这件事,绑定到指定方法上(AOP的核心:无侵入式增强)
简单说:Spring AOP事务控制 = 用AOP的思想,给指定方法批量加事务管理
二、经典款:XML配置AOP事务控制
这是传统项目里最常见的写法,虽然配置多,但逻辑清晰,先上完整配置,再逐个拆解:
关键配置解读
| 配置项 | 作用 | 新手必看 |
|---|---|---|
transaction-manager |
指定事务管理器 | 必须和上面定义的事务管理器id一致 |
name="get*" |
方法名匹配规则 | 通配符*表示"以get开头的所有方法" |
propagation="SUPPORTS" |
事务传播行为 | 支持事务:有就用,没有也能跑(查询专用) |
read-only="true" |
只读事务 | 查询时设置,Spring会做性能优化 |
execution(* com.hg.service.*.*(..)) |
切点表达式 | 包名.类名.方法名(参数),*通配所有,..通配任意参数 |
三、简约款:注解式事务控制
XML配置虽好,但太繁琐!Spring给我们准备了更优雅的注解方式,几行代码搞定:
步骤1:开启注解扫描
先在Spring配置文件里加一行,告诉Spring要扫描@Transactional注解:
步骤2:加注解(3种加法,按需选择)
四、踩坑预警!事务失效的常见场景
最气人的不是不会配,而是配了没用!这两个高频坑,新手90%都会踩:
坑1:Service层自己try-catch了异常
解决方案:
-
方案1:catch里手动抛运行时异常
-
方案2:指定rollbackFor包含检查型异常
坑2:方法名不匹配XML里的规则
比如XML里配的是name="get*",但你写的方法名是findUserById(),事务就不会生效!
解决方案:
-
要么改方法名:
getUserById() -
要么改XML规则:
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/> -
注解式无此问题(注解直接绑方法)
额外加餐:其他常见失效场景
-
非public方法(Spring事务只对public方法生效)
-
同一个类内方法调用(AOP代理失效)
-
数据源没配置事务管理器
-
传播行为设成了
NOT_SUPPORTED(不支持事务)
五、XML vs 注解:怎么选?
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| XML | 集中管理,不侵入代码 | 配置繁琐,维护成本高 | 老项目、需要统一管控所有事务 |
| 注解 | 简洁灵活,按需配置 | 分散在代码中,不易全局查看 | 新项目、微服务、灵活度要求高 |
总结
-
Spring事务控制的核心是AOP思想:通过切面给指定方法批量加事务规则,无需修改业务代码;
-
XML配置适合全局管控,注解配置更简洁灵活,可根据项目场景选择;
-
事务失效的核心原因:Spring没感知到异常 或 方法没匹配到事务规则,优先检查try-catch和方法名匹配问题。
最后留个小思考题:如果一个方法既有XML事务规则,又加了@Transactional注解,哪个会生效?评论区告诉我答案吧!
如果觉得有用,记得点赞+收藏+关注,后续持续更新Spring避坑指南!