@AfterThrowing用于异常时记录日志,需显式声明throwing属性绑定异常,配合JoinPoint获取上下文,结合切点精准定位;需与@Around协同实现异常拦截与转换。

Spring AOP 提供了优雅的方式,在不侵入业务代码的前提下统一处理异常并记录日志。关键在于用 @AfterThrowing 捕获异常,配合环绕通知或切点表达式精准定位目标方法,再通过参数注入(如 JoinPoint、异常对象)实现上下文感知的日志增强。
明确异常通知的触发条件
@AfterThrowing 是专为异常场景设计的通知类型,它只在目标方法抛出指定异常时执行,不会干扰正常流程。这点区别于 @After(总会执行)或 @Around(需手动控制流程)。
- 必须显式声明
throwing属性,绑定异常形参,否则无法获取异常实例 - 切点表达式应聚焦具体层,例如
@within(org.springframework.stereotype.Service)或更细粒度的execution(* com.example.service..*.*(..)) - 若需捕获自定义异常,确保异常类在切点范围内被抛出,且未被上层 try-catch 吞掉
注入异常与执行上下文变量
Spring AOP 允许在通知方法中直接接收运行时信息,无需手动反射提取:
-
JoinPoint joinPoint:提供方法签名、参数值、目标对象等基础信息 -
Throwable exception:由throwing="exception"绑定,可调用getMessage()、getStackTrace()等 - 还可结合
RequestContextHolder获取当前 HTTP 请求信息(Web 环境下)
构建可读性强的日志内容
避免只打印堆栈,应结构化输出关键诊断字段:
- 记录完整方法签名:
joinPoint.getSignature().toShortString() - 打印入参快照(注意脱敏敏感字段,如密码、身份证号)
- 包含异常类型、消息、时间戳、请求唯一 ID(如 traceId)便于链路追踪
- 示例日志格式:
[ERROR] ServiceException in UserService.updateUser(id=123): Validation failed - email format invalid
与环绕通知协同做异常兜底
仅靠 @AfterThrowing 无法修改返回值或阻止异常传播。如需统一转换异常为响应体(如 REST API 返回标准错误码),推荐用 @Around 包裹逻辑:
- 在
proceed()后 catch 异常,做日志 + 转换,再 rethrow 或返回友好结果 - 若既要记录日志又要拦截异常,
@Around更灵活;若只需旁观式记录,@AfterThrowing更轻量、语义清晰 - 两者可共存:环绕用于控制流,异常通知用于审计留痕

















