AOP 日志入门
1. 一句话简介
AOP(面向切面编程)通过切面类将横切逻辑(如日志记录)从业务代码中剥离出来,统一拦截方法调用并按需插入逻辑。本模块使用 @Aspect + @Around 环绕通知,在 Controller 方法执行前后自动采集 URL、IP、请求参数、返回值、耗时、浏览器与操作系统信息,并输出为 JSON 日志。核心优势是零侵入:TestController 的方法里没有一行日志代码,所有记录动作都由 AopLog 切面在运行时完成。
2. 什么时候使用
✅ 适用场景
- 需要为所有(或某类)接口统一记录请求日志,且不想逐个方法重复编写日志代码。
- 希望在记录日志的同时拿到方法参数名与参数值(
MethodSignature.getParameterNames()+joinPoint.getArgs()),这在 Filter/Interceptor 中难以直接获得。 - 需要采集 HTTP 层面的附加信息:客户端 IP(支持 Nginx
x-forwarded-for等代理头)、User-Agent、浏览器与操作系统类型,用于访问来源分析。 - 需要统计接口耗时用于性能基线,或为后续扩展成审计日志、接口监控、埋点统计预留统一入口。
- 项目采用 Spring Bean 管理 Controller/Service,符合 AOP 的代理机制前提。
❌ 不适用/需谨慎
- 仅能拦截 Spring Bean 的方法:Spring AOP 基于动态代理,
static方法、final类/方法、以及未被 Spring 容管的类无法被织入。 - 对性能敏感的高并发入口:环绕通知通过代理多了方法调用层和反射取参,且日志串行输出会增加开销,超高频请求慎用或需配合异步日志。
- 需要区分精确日志级别/细粒度开关时:想按单个接口单独配置或关闭日志,需额外引入自定义注解与匹配逻辑,框架本身不提供。
- 仅看请求到达而不关心方法参数与返回值时:Filter 或 Interceptor 更轻量、更早、可覆盖包括静态资源在内的入口。
- 需要跨进程/跨服务的分布式链路追踪(TraceId 串联)时:原生 AOP 日志无分布式上下文,需与链路追踪框架结合。
3. 常见业务场景
统一接口访问日志:为所有 Controller 接口自动记录谁(IP)、何时、访问哪个 URL(request.getRequestURL())、HTTP 方法(GET/POST/PUT/DELETE)与耗时,直接对应当前模块一次性覆盖 *Controller 全部方法的逻辑,避免每个接口手写日志。
接口参数与返回快照:通过反射同时拿到方法参数名(getParameterNames())与参数值(getArgs()),组装成参数名→值的映射打印,配合 result 字段记录返回结果,用于问题排查时回放具体入参(如模块中 /test?who=kiro 与 /testJson {name} 两个接口的入参回显)。
来源分析与客户端识别:解析 User-Agent 头得到浏览器(getBrowser())与操作系统(getOperatingSystem()),结合 getIp() 多级代理头校验(x-forwarded-for → Proxy-Client-IP → WL-Proxy-Client-IP → getRemoteAddr()),可做访问来源、客户端画像统计。
接口性能监控:@Around 在 point.proceed() 前后取 System.currentTimeMillis() 差值得到 timeCost(耗时字段),配合线程名/线程 ID 输出,能快速发现慢接口并定位到具体类方法(classMethod)。
审计与合规日志:将记录了操作人(IP)、操作对象(URL+参数)、操作时间与结果的 JSON 日志落到文件(通过 logback-spring.xml 的 FILE_INFO/FILE_ERROR 按天滚动归档),满足审计追溯需求,且因零侵入不会污染业务代码。
4. 同类技术对比
| 方案 | 拦截层级 | 能否获取方法参数名/值 | 侵入性 | 性能开销 | 适用规模/范围 | 学习成本 |
|---|---|---|---|---|---|---|
| Spring AOP(本模块) | 业务方法(代理) | 能,二者均可 | 零侵入 | 中(反射+代理) | 任意规模的 Spring Bean 方法级日志 | 低 |
| Filter | Servlet 容器 | 不能,只有原始 request | 低(注册一次) | 低 | 匹配静态资源、基础安全、请求头过滤 | 低 |
| HandlerInterceptor | Spring MVC 层 | 难直接取参,需另解析 | 低 | 低 | 登录校验、权限、MVC 层拦截 | 低 |
| 硬编码/日志框架 | 散落在业务代码 | 天然可见 | 高(每方法重复) | 最低 | 小项目、点状记录 | 最低 |
选型建议
- 只要目标是记录方法参数、返回值与耗时,且不想碰业务代码,首选 Spring AOP;本模块所示
@Aspect + @Around是大部分日志、审计、监控需求的标准答案。 - 若只需在请求最外层做一次粗粒度处理(如统一设置响应头、CORS、基础 IP 黑名单),Filter 更轻、覆盖面更广(含静态资源)。
- 需要在进入 Controller 前做鉴权/参数校验且关心 Handler 信息时,HandlerInterceptor 语义更贴合。
- 单接口或临时排错,直接
log.info硬编码最直接,但量多时应回归 AOP 以保持代码整洁。 - 若要把日志打进分布式链路、或用 Spring Boot Actuator 做指标采集,则 AOP 之上还要叠加对应的链路跟踪/监控组件,而非仅靠切面日志本身。