首页 > 解决方案 > 来自 ExceptionHandler 的 @AfterReturning 不起作用

问题描述

我有一个 GlobalExceptionHandler 类,其中包含多个用 @ExceptionHandler 注释的方法。

@ExceptionHandler({ AccessDeniedException.class })
public final ResponseEntity<Object> handleAccessDeniedException(
  Exception ex, WebRequest request) {
    return new ResponseEntity<Object>(
      "Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}

我有一个 AOP,假设在异常处理程序返回响应后触发。

@AfterReturning(value="@annotation(exceptionHandler)",returning="response")  
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}

但是在处理程序返回有效响应后,不会触发 @AfterReturning。

尝试了完整的限定名但不起作用

@AfterReturning(value = "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)", returning = "response"){
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
  //do something
}

标签: spring-aop

解决方案


请阅读文档以了解 Spring 框架中的代理机制。

假设ExceptionHandler编写的代码具有以下格式

@ControllerAdvice
public class TestControllerAdvice {
    @ExceptionHandler({ AccessDeniedException.class })
    final public ResponseEntity<Object> handleAccessDeniedException(
      Exception ex, WebRequest request) {
        return new ResponseEntity<Object>(
          "Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
    }
}

与该问题有关的文档中的关键点是

  1. Spring AOP 使用 JDK 动态代理或 CGLIB 为给定的目标对象创建代理。

  2. 如果要代理的目标对象实现了至少一个接口,则使用 JDK 动态代理。目标类型实现的所有接口都被代理。如果目标对象没有实现任何接口,则创建一个 CGLIB 代理。

  3. 使用 CGLIB,不能建议最终方法,因为它们不能在运行时生成的子类中被覆盖。

  • OP 根据评论和提示确定了该问题,此答案可供将来参考。

推荐阅读