Java自定义异常需继承RuntimeException,AOP用@Around精准拦截并统一处理,配合@ApiError注解实现接口级差异化提示,与@ControllerAdvice分工协作。

Java 自定义异常在 AOP 切面中被统一拦截,关键在于两点:一是自定义异常需继承 RuntimeException(避免强制 try-catch),二是 AOP 切面通过 @Around 或异常通知逻辑精准匹配该异常类型或其注解语义。
自定义异常要符合运行时异常规范
必须继承 RuntimeException,不能是 checked 异常(如 Exception 及其子类,IOException 等)。Spring AOP 默认只织入运行时异常的处理流程,且业务方法无需声明 throws,保持干净。
- 推荐写法:
public class BusinessException extends RuntimeException - 可添加业务字段,如
private int code;、private String tip;,便于统一响应包装 - 构造函数建议支持
(code, message)和(message)两种形式,兼顾灵活性与默认语义
AOP 切面按异常类型精准拦截
使用 @Around 或结合 @AfterThrowing 拦截指定异常。推荐 @Around,因它能控制整个执行流,统一返回格式、记录日志、甚至重试。
- 切点表达式示例:
@Around("execution(* com.example.controller..*.*(..)) && args(..)") - 在环绕逻辑中捕获异常:
if (throwable instanceof BusinessException) { ... } - 不建议用
catch (Exception e)宽泛捕获——会吞掉本该由 @ControllerAdvice 处理的系统级异常(如 SQLException)
配合注解实现接口级差异化提示
同一 BusinessExeption 在不同接口含义不同,硬编码提示语不灵活。可用自定义注解 + AOP 读取上下文信息。
立即学习“Java免费学习笔记(深入)”;
- 定义注解:
@Target(METHOD) @Retention(RUNTIME) public @interface ApiError { String value() default "操作失败"; } - 在 Controller 方法上标注:
@ApiError("订单支付已失效") public Result pay(...) { ... } - AOP 中通过
joinPoint.getSignature().getDeclaringType()和getDeclaredAnnotations()提取注解值,覆盖默认错误消息
注意和 @ControllerAdvice 的分工协作
AOP 不替代全局异常处理器,而是互补:
- @ControllerAdvice 负责最终 HTTP 响应结构(状态码、JSON body)、兜底未被捕获的 RuntimeException
- AOP 负责在方法执行过程中增强逻辑:如前置校验、后置数据脱敏、异常语义增强、操作日志等
- 若 AOP 中已对 BusinessException 做了完整处理并返回 Result 对象,就不要再抛出——否则会重复进入 @ControllerAdvice


















