Java中AOP统一打印方法入参和异常的核心是:@Before获取参数并脱敏、补充上下文后结构化输出;@AfterThrowing捕获异常并精简堆栈;推荐按注解或包+层精准切点,避免性能损耗。

Java中利用AOP统一打印方法入参和异常堆栈,核心是结合 @Before 捕获参数、@AfterThrowing 捕获异常,并通过 JoinPoint 和绑定的 Throwable 参数获取上下文与堆栈信息。不需修改业务代码,日志可结构化、可脱敏、可追踪。
精准定义切点,只拦截目标方法
避免全包扫描带来的性能开销和误打日志,推荐两种方式之一:
- 按注解切:自定义如
@LogArgs或@Trace,仅在需要的日志方法上标注,语义清晰、控制粒度细 - 按包+层切:例如
execution(* com.example.controller..*.*(..))或@within(org.springframework.stereotype.Controller),适合全量 Controller 日志 - 排除文件上传、流式响应等特殊方法(如含
MultipartFile或InputStream参数),防止 JSON 序列化失败
前置通知打印入参,注意安全与可读性
@Before 在方法执行前触发,适合记录请求快照:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
joinPoint.getArgs()获取参数数组,配合 Gson 或 Jackson 序列化(不用 Fastjson,避免上传接口报错) - 敏感字段必须脱敏:手机号中间四位替换成
****,身份证号保留前后 4 位,密码字段直接过滤为[REDACTED] - 补充上下文:HTTP 方法、URL、客户端 IP(从
RequestContextHolder提取)、traceId(用于链路追踪) - 日志格式示例:
[INFO] POST /api/user/update, IP: 192.168.1.100, traceId: abc123, args: {"id":123,"email":"user@***.com"}
异常通知捕获堆栈,结构化输出关键信息
@AfterThrowing 是专为异常设计的通知,只在抛出指定异常时执行,不干扰正常流程:
立即学习“Java免费学习笔记(深入)”;
- 必须显式声明
throwing = "e",并在方法签名中接收Throwable e,否则拿不到异常实例 - 不要只调
e.printStackTrace():提取e.getClass().getSimpleName()、e.getMessage()、时间戳、方法签名joinPoint.getSignature().toShortString() - 堆栈建议截取前 5 行(或限制字符数),避免日志爆炸;完整堆栈可异步写入独立 error-log 文件或发告警
- 示例日志:
[ERROR] ValidationException in UserController.updateUser(): Email format invalid — at UserController.java:42
进阶:与 @Around 协同实现异常兜底(可选)
若需统一转换异常为标准响应体(如 REST 接口返回 { "code": 500, "msg": "系统繁忙" }),单靠 @AfterThrowing 不够:
- 用 @Around 包裹方法执行,在
proceed()后 catch 异常,完成日志 + 转换 + 返回 - 此时 @AfterThrowing 仍可保留,作为审计留痕(谁、何时、在哪抛了什么异常),与业务兜底逻辑解耦
- 注意通知优先级:@Around 默认高于 @AfterThrowing,若需严格顺序,可用
@Order显式控制


















