基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

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:目标方法正常执行(没有异常)

  1. @Around (环绕通知的前半部分)
  2. @Before (前置通知)
  3. 🎯 [目标方法执行]
  4. @AfterReturning (正常返回通知)
  5. @After (最终通知)
  6. @Around (环绕通知的后半部分,即 proceed() 之后的代码)

情况 B:目标方法抛出异常

  1. @Around (环绕通知的前半部分)
  2. @Before (前置通知)
  3. 🎯 [目标方法执行,抛出异常]
  4. @AfterThrowing (异常通知)
  5. @After (最终通知)
    (注意:此时 @AfterReturning@Around 的后半部分将不会执行,除非你在 @Around 内部用 try-catch 手动吞掉了异常)

总结建议
在日常开发中,能用简单的 @Before@AfterReturning 解决的问题,尽量不要用 @Around,以保持代码的简单性和性能;如果是做耗时统计、缓存等需要控制方法执行流的场景,则首选 @Around

00:00
00:00