下面这份内容给你的是工程级、可对照代码理解的 Spring Boot AOP 通知模型,而不是“背注解名词”。
⸻
一、什么是 Advice(通知)?
Advice =
当切点命中某个方法时,你要在这个方法执行的哪个阶段插入什么逻辑
也就是:
拦住 → 在哪一刻 → 干什么
⸻
二、Spring AOP 支持的 5 种通知类型
这是一个方法生命周期模型:
调用开始
↓
@Before
↓
目标方法执行
↓
正常返回 → @AfterReturning
抛异常 → @AfterThrowing
↓
@After(最终)
@Around 可以包住整个过程
⸻
三、@Before —— 方法执行前
用途
• 权限校验
• 参数校验
• 幂等校验
@Before("@annotation(LoginRequired)")
public void checkLogin() {
if (!LoginContext.isLogin()) {
throw new UnauthorizedException();
}
}
只要抛异常,方法根本不会执行
⸻
四、@AfterReturning —— 只在成功后
用途
• 成功日志
• 成功计数
• 业务审计
@AfterReturning(
value = "@annotation(BizLog)",
returning = "result"
)
public void logSuccess(Object result) {
log.info("success, result={}", result);
}
如果抛异常,这个不会执行
⸻
五、@AfterThrowing —— 只在异常时
用途
• 异常报警
• 失败日志
• 风控拦截
@AfterThrowing(
value = "@annotation(BizLog)",
throwing = "ex"
)
public void logFail(Exception ex) {
log.error("biz error", ex);
}
⸻
六、@After —— finally 语义
用途
• 资源释放
• ThreadLocal 清理
• 结束打点
@After("@annotation(BizLog)")
public void clearContext() {
TraceContext.clear();
}
无论成功失败都会执行
⸻
七、@Around —— 核武器
@Around 是唯一一个可以:
决定方法是否执行、执行几次、返回什么
用途
• 事务
• 日志
• 性能
• 限流
• 幂等
@Around("@annotation(BizLog)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
Object result = pjp.proceed();
log.info("success cost={}", System.currentTimeMillis() - start);
return result;
} catch (Throwable e) {
log.error("fail", e);
throw e;
}
}
⸻
八、你什么时候用哪个?
场景 用什么
要拦截、不让方法跑 @Before
只关心成功 @AfterReturning
只关心异常 @AfterThrowing
要做清理 @After
要包住整个过程 @Around
⸻
九、工程铁律
在真实系统里:
90% 的切面都应该用 @Around
因为:
• 你需要耗时
• 你需要异常
• 你需要返回值
• 你需要控制执行
Spring 事务、缓存、重试
全部是 @Around
⸻
十、你现在已经具备“读懂 Spring 源码”的能力了
你已经知道:
Spring AOP 的全部能力,就是围绕这 5 个通知类型组合出来的
@Transactional、@Cacheable、@Retryable
本质都是它们的变体
⸻
如果你愿意,我可以下一步给你讲一个非常关键但少有人懂的点:
为什么 @Around 一旦写错,就会让你的事务、异常、返回值全部失效