Java可通过自定义注解+AOP自动统计方法耗时:定义@Target(METHOD)@Retention(RUNTIME)注解标记方法,编写@Around切面用System.nanoTime()记录执行时间并输出结构化日志,需引入spring-boot-starter-aop、加@Aspect@Component,注意仅支持public方法,异步场景需结合ThreadLocal或Sleuth透传上下文。

Java 中可以通过自定义注解 + AOP(面向切面编程)实现方法耗时统计的自动化,无需在每个方法里手动写开始/结束时间代码。
定义耗时统计注解
创建一个自定义注解,用于标记需要统计执行时间的方法:
(推荐用 @Target(ElementType.METHOD) 和 @Retention(RetentionPolicy.RUNTIME))- 加上 @Documented 和 @Inherited 可选,按需添加
- 可定义属性如 logLevel(控制日志级别)、includeParams(是否打印入参)等,增强灵活性
- 注解本身不包含逻辑,只起标记作用
编写 AOP 切面拦截方法调用
使用 Spring AOP 或 AspectJ,在注解标记的方法执行前后自动记录时间:
- 在 @Around 增强中获取当前时间戳(如 System.nanoTime(),精度更高)
- 执行目标方法后计算耗时(单位建议转为毫秒并保留小数,如 TimeUnit.NANOSECONDS.toMillis(elapsed))
- 结合 SLF4J 或 Logback,按方法名、耗时、参数(若开启)生成结构化日志,例如:
INFO [traceId] com.example.service.UserService.findById() took 12.34ms - 异常情况下也应记录耗时和错误信息,便于排查慢请求与失败原因
集成到 Spring Boot 项目中
确保 AOP 能生效,注意以下几点:
立即学习“Java免费学习笔记(深入)”;
- 引入 spring-boot-starter-aop 依赖
- AOP 类加上 @Aspect 和 @Component,让 Spring 扫描到
- 避免切到内部调用(private / this.调用),因 Spring AOP 默认基于代理,仅对 public 方法有效
- 如需更彻底的拦截(如 private 方法),可考虑 AspectJ 编译期织入,但会增加构建复杂度
进阶:支持异步方法与上下文透传
对于 @Async 或 WebFlux 场景,需额外处理:
- 普通 AOP 无法捕获异步线程中的方法调用,需配合 ThreadLocal 或 MDC 传递 traceId、耗时上下文
- 可结合 Sleuth/Brave 实现分布式链路追踪,把耗时日志纳入整体 trace 中
- Web 层(如 Controller)也可加该注解,但要注意是否与全局异常处理、统一响应封装冲突


















