这一块是 数据库一致性 + AOP实际应用的核心场景
一、先给结论(事务本质)
❗ Spring 事务 = 通过 AOP + 数据库事务能力,实现"要么全部成功,要么全部失败"
二、现实问题(为什么需要事务)
假设你做下单逻辑:1. 扣库存、2. 创建订单、3. 扣余额
❌ 没有事务的问题
执行到一半:
1. 扣库存 ✔
2. 创建订单 ✔
3. 扣余额 ❌(失败)
结果:
-
库存没了
-
订单存在
-
钱没扣
👉 数据不一致
三、事务解决方案
Spring 事务保证:
❗ 要么全部成功,要么全部回滚
四、@Transactional 是什么?
❗ 给这个方法加了一个AOP 事务拦截器
java
@Transactional
public void createOrder() {
orderMapper.insert();
stockMapper.decrease();
payMapper.pay();
}
五、事务执行全过程(核心链路)
当你调用方法时:
java
Controller → Service.createOrder()
实际流程:
AOP代理拦截
↓
开启事务(Connection.setAutoCommit(false))
↓
执行方法
↓
成功 → commit
失败 → rollback
六、事务本质(非常重要)
Spring 事务本质是:
❗ 对 JDBC Connection 的封装
JDBC原始写法:
java
conn.setAutoCommit(false);
try {
// SQL1
// SQL2
conn.commit();
} catch (Exception e) {
conn.rollback();
}
Spring写法:
java
@Transactional
public void method() {}
👉 Spring帮你做了上面所有事
七、为什么事务依赖 AOP?
因为:
事务必须在"方法执行前后"插入逻辑
AOP结构:
@Before → 开启事务
@AfterReturning → 提交事务
@AfterThrowing → 回滚事务
八、事务的执行时机(关键)
方法开始 → 开启事务
方法正常结束 → commit
方法抛异常 → rollback
九、默认回滚规则(重要)
Spring 默认:
❗ 只有 RuntimeException才回滚
RuntimeException = 编程错误
Exception = 业务可控异常
示例:
✔ 会回滚
throw new RuntimeException();
❌ 不回滚
throw new Exception();
十、所有异常回滚------rollbackFor(企业常用)
java
@Transactional(rollbackFor = Exception.class)
意思:
所有异常都回滚
十一、事务失效的经典坑(重点)
❌ 1. 方法内部调用(最常见)
public void a() {
b(); // ❌ 事务失效
}
@Transactional
public void b() {}
原因:
没走代理对象
❌ 2. private 方法
@Transactional
private void method() {}
Spring 无法代理
❌ 3. 同类调用
this.method();
绕过 AOP
十二、事务传播机制(进阶核心)
常见传播行为:
1️⃣ REQUIRED(默认)有事务就加入,没有就新建
2️⃣ REQUIRES_NEW 强制开启新事务
3️⃣ SUPPORTS 有就用,没有就不用
十三、结合你 minishop 项目
以后你的订单逻辑:
java
@Transactional
public void createOrder() {
stockService.decrease(); // 扣库存
orderService.create(); // 创建订单
payService.pay(); // 扣款
}
发生异常:
payService.pay()失败
👉 整个方法:
自动回滚(库存恢复,订单删除)
十四、事务 + AOP + IOC 三者关系(核心)
IOC:负责创建对象
AOP:负责增强行为
Transaction:AOP的一个具体应用
十五、面试级总结
Spring事务本质是基于AOP的声明式事务管理,
通过拦截方法,在执行前开启事务,
执行成功提交,异常时回滚,
底层依赖JDBC的Connection事务机制