spring boot 全局异常处理可以通过配置 @controlleradvice 结合 @exceptionhandler 来捕获 aop 调用过程中抛出的异常。核心做法是在切面中抛出异常,并在 advice 类中定义针对该异常类型的处理方法,这样就能统一拦截并返回标准化的错误响应。

AOP 切面如何正确抛出异常
在 AOP 切面中,如果业务逻辑或前置/后置检查失败,必须显式使用 throw 语句抛出异常对象。只要异常没有被切面内部吞掉,它就会沿着调用栈向上传播,最终被 Spring MVC 的异常处理机制捕获。关键在于确保切面方法签名允许抛出受检异常,或者在非受检异常路径下直接抛出 RuntimeException 的子类。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SecurityCheckAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object checkSecurity(ProceedingJoinPoint joinPoint) throws Throwable {
// 模拟安全检查失败
boolean isAllowed = false;
if (!isAllowed) {
throw new SecurityException("Access denied by AOP");
}
return joinPoint.proceed();
}
}
上述代码展示了在 @Around 切面中,当条件不满足时直接抛出 SecurityException。由于该方法声明了 throws Throwable,该异常会穿透切面层,进入 Spring MVC 的请求处理流程。开发者只需确保切面逻辑中的异常抛出路径是可达的,全局异常处理器就能接收到它。
全局异常处理器如何匹配并处理异常
全局异常处理器通过 @ControllerAdvice 注解的类来实现,其中使用 @ExceptionHandler 指定要处理的异常类型。当 AOP 抛出的异常到达控制器层时,Spring 会查找匹配的异常处理器。如果切面抛出的是自定义异常,Advice 中应定义对应类型的处理方法,返回 ResponseEntity 以控制 HTTP 状态码和响应体内容。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(SecurityException.class)
public ResponseEntity<string> handleSecurityException(SecurityException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("Security Violation: " + ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<string> handleGenericException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Internal Error: " + ex.getMessage());
}
}</string></string>
在这个示例中,handleSecurityException 专门处理由 AOP 切面抛出的 SecurityException。由于 @ExceptionHandler 的优先级高于通用异常处理,它能精确拦截特定错误。开发者需要注意,如果切面中抛出了未捕获的运行时异常,且没有对应的具体 @ExceptionHandler,则会 fallback 到通用的 Exception 处理器。这种分层处理确保了 AOP 异常能被准确识别和响应。
当 AOP 抛出非 RuntimeException 时会发生什么
如果 AOP 切面中抛出的是受检异常(Checked Exception),例如 IOException 或自定义的受检异常,而全局异常处理器只定义了 @ExceptionHandler(RuntimeException.class),那么该异常将不会被捕获,导致请求返回 500 错误并由默认错误页面处理。这是因为 Spring MVC 的默认异常解析器主要关注非受检异常,除非显式配置或添加对应的处理器。











