Spring Boot 在处理异常时,会从上到下查找最具体的 @ExceptionHandler 方法

  1. 先看是否有匹配的异常处理方法(CustomException.class)。

  2. 如果找到,就调用对应的方法,不再继续查找。

  3. 如果找不到,就会向上寻找更通用的异常处理方法(比如 Exception.class)。

你的代码执行逻辑

如果你抛出了 CustomException

  • Spring 发现 @ExceptionHandler(CustomException.class) 正好匹配 CustomException只会执行这个方法

  • @ExceptionHandler(Exception.class) 是兜底的(更泛型的异常处理),不会执行

如果你抛出的是 NullPointerExceptionRuntimeException

  • Spring 找不到 @ExceptionHandler(NullPointerException.class),会走 @ExceptionHandler(Exception.class) 这个兜底方法。

验证代码

你可以在 CustomException 处理方法和 Exception 处理方法里分别加上不同的日志:

@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult exception(CustomException e){
    log.warn("Handled by CustomException handler: {}", e.getMessage());
    return ResponseResult.errorResult(e.getAppHttpCodeEnum());
}

@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult exception(Exception e){
    log.error("Handled by Exception handler: {}", e.getMessage());
    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
}

然后在代码里抛出 CustomException

throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);

你会发现日志只会打印 Handled by CustomException handler: xxx,而 Exception 处理方法不会触发。


总结

CustomException 只会被 @ExceptionHandler(CustomException.class) 处理
Exception.class 处理方法只是兜底,不会拦截 CustomException
Spring 只会执行一个最匹配的 @ExceptionHandler 方法,不会执行多个