Spring AOP 提供了哪几种通知(Advice)类型(如前置、后置、环绕等)?
Spring AOP 一共提供了 5 种 通知(Advice)类型。它们决定了切面逻辑在目标方法执行过程中的哪个时间点运行。
以下是这 5 种通知类型的详细分类和说明:
1. 前置通知 (Before Advice)
- 注解:
@Before - 执行时机:在目标方法执行之前运行。
- 特点:除非在通知内部抛出异常,否则它无法阻止目标方法的执行。
- 常见应用场景:权限校验、参数校验、记录请求的入参日志等。
2. 正常返回通知 / 后置返回通知 (After Returning Advice)
- 注解:
@AfterReturning - 执行时机:在目标方法正常执行完毕并返回结果之后运行。
- 特点:只有当目标方法没有抛出任何异常时才会执行。可以通过配置获取目标方法的返回值。
- 常见应用场景:对返回值进行加工处理、记录成功的操作日志、清理特定的缓存等。
3. 异常通知 / 抛出异常通知 (After Throwing Advice)
- 注解:
@AfterThrowing - 执行时机:在目标方法执行过程中抛出异常退出时运行。
- 特点:可以通过配置获取抛出的具体异常对象,甚至可以指定只拦截特定类型的异常。
- 常见应用场景:统一的异常记录(错误日志)、发送告警邮件/消息、事务回滚处理。
4. 最终通知 / 后置通知 (After (Finally) Advice)
- 注解:
@After - 执行时机:在目标方法执行结束之后运行,无论正常返回还是抛出异常,都会执行。
- 特点:它的作用类似于 Java 中
try-catch-finally语句里的finally块。注意它无法获取目标方法的返回值(获取返回值需用@AfterReturning)。 - 常见应用场景:释放资源(如关闭文件流、关闭数据库连接、清除 ThreadLocal 中的数据等)。
5. 环绕通知 (Around Advice)
- 注解:
@Around - 执行时机:包围目标方法的整个执行过程。它可以在目标方法调用前后完成自定义的行为。
- 特点:这是最强大、最灵活的通知类型。
- 必须显式调用
ProceedingJoinPoint.proceed()方法来让目标方法执行,如果不调用,目标方法将被拦截不会执行。 - 它可以自由地修改入参、修改返回值,甚至捕获异常后返回自定义结果。
- 必须显式调用
- 常见应用场景:接口性能耗时统计、分布式锁的控制、数据库事务管理、动态数据源切换等。
💡 核心进阶:这5种通知的执行顺序是怎样的?
在实际开发和面试中,执行顺序非常重要。Spring 5.2.7 及以上版本(对应 Spring Boot 2.3+) 对 AOP 的执行顺序进行了重构,使其更加符合直觉。
假设我们将这 5 种通知写在同一个切面类中:
情况 A:目标方法正常执行(没有异常)
@Around(环绕通知的前半部分)@Before(前置通知)- 🎯 [目标方法执行]
@AfterReturning(正常返回通知)@After(最终通知)@Around(环绕通知的后半部分,即proceed()之后的代码)
情况 B:目标方法抛出异常
@Around(环绕通知的前半部分)@Before(前置通知)- 🎯 [目标方法执行,抛出异常]
@AfterThrowing(异常通知)@After(最终通知)
(注意:此时@AfterReturning和@Around的后半部分将不会执行,除非你在@Around内部用try-catch手动吞掉了异常)
总结建议:
在日常开发中,能用简单的 @Before 或 @AfterReturning 解决的问题,尽量不要用 @Around,以保持代码的简单性和性能;如果是做耗时统计、缓存等需要控制方法执行流的场景,则首选 @Around。