Spring 通知有哪些类型?
- 标签:后端、Spring
🏛 业务架构师
Spring AOP 有五种通知类型,我按一次方法调用的时序讲,并附上业务适用场景:
- @Before(前置通知):方法执行前。用于权限校验、参数补全、防重检查——把非法请求拦在业务执行前,省下游资源;
- @After(后置通知):方法执行后(无论成功失败),类似 finally 的清理场景;
- @AfterReturning(返回通知):成功返回后。用于结果加工、成功埋点;
- @AfterThrowing(异常通知):抛异常后。用于异常告警、失败留痕(接 Sentry/钉钉机器人);
- @Around(环绕通知):包裹整个方法执行,可控制是否执行目标、改写入参返回值。功能最全:限流、耗时监控、缓存、幂等都靠它。
实战经验两条:
- 能用 @Before/@AfterReturning 就别用 @Around。环绕通知要自己处理 try/finally 和 proceed 异常,写错就吞异常或漏调用,是线上事故高发点。通知类型选"表达力刚好够"的,错误面最小;
- 异常通知里只做记录不做兜底。在切面里 catch 住业务异常返回默认值,会让上游误判成功,造成静默资损。降级逻辑要有明确业务评审。
架构治理角度:公司级切面(监控、审计、鉴权)统一封装成 starter,业务方只加注解。通知类型是工具,统一供给才是资产化。
🏗 系统架构师
五种:
- @Before:方法执行前(鉴权、参数校验);
- @After:finally 语义,成败都执行(清理资源);
- @AfterReturning:正常返回后(结果加工、审计);
- @AfterThrowing:抛异常后(异常告警上报);
- @Around:包裹全流程,显式控制是否与何时调用
proceed()——最强大也最危险。
我的使用纪律:
- 能用具体通知就不用 Around——Around 忘调 proceed、吞异常、改返回值的自由度太大,是切面事故的主要来源;
- 多切面叠加用
@Order显式声明顺序(值越小越外层),否则「事务提交后才写审计」还是「先审计后提交」全凭运气; - 切面内不写业务分支逻辑,只做转发、包装、度量——切面一旦带业务状态,全服务的行为一致性就失控了。
💻 全栈开发专家
五种:
java
@Aspect
@Component
public class DemoAspect {
@Before("pointcut()") // 1. 方法前
public void before(JoinPoint jp) { }
@After("pointcut()") // 2. 类似 finally,正常异常都执行
public void after(JoinPoint jp) { }
@AfterReturning(value = "pointcut()", returning = "ret") // 3. 正常返回后
public void afterRet(Object ret) { }
@AfterThrowing(value = "pointcut()", throwing = "e") // 4. 抛异常后
public void afterEx(Exception e) { }
@Around("pointcut()") // 5. 环绕:前四个的超集
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
return pjp.proceed(); // 放行目标方法,只调一次
} finally {
metrics.record(pjp.getSignature(), System.currentTimeMillis() - start);
}
}
}实践偏好:统一用 @Around 一个打天下——耗时统计、返回值改写、异常转译都能做,控制流清晰。铁律:proceed() 只调一次,重复调用等于业务执行两遍(幂等切面里见过这种事故)。
同一切面内执行顺序:Around 前置 → Before → 目标方法 → AfterReturning/AfterThrowing → After → Around 后置。多切面按 @Order 值小的在外层,洋葱圈模型记不错。