Spring Boot 监控:AOP vs Filter vs Java Agent
01前言
在 高并发 + 微服务 中,
传统 手动埋点(System.currentTimeMillis())就像用体温计量火箭速度——代码侵入、重复劳动、维护爆炸。
下文是无侵入、高精度、全链路 监控 API 耗时,全程不碰业务代码的方案!
02实战:6 种方案横向对比
03方案详解
方案 1:StopWatch(临时调试)
代码:
@GetMapping("/query")
public ResponseEntity<String> query() throws Exception {StopWatch stopWatch = new StopWatch(); // 创建计时器stopWatch.start(); // 开始计时TimeUnit.MILLISECONDS.sleep(new Random().nextLong(2000)); // 模拟业务stopWatch.stop(); // 结束计时System.out.printf("**方法耗时:%dms**%n", stopWatch.getTotalTimeMillis());return ResponseEntity.ok("api query...");
}
注解:
- StopWatch 是 Spring 提供的轻量级计时工具。
- 侵入性强:需手动插入到业务代码中。
- 适合 临时调试,生产环境 不推荐。
方案 2:AOP 切面(无侵入)
代码:
@Aspect // 声明切面
@Component
public class PerformanceAspect {private static final Logger logger = LoggerFactory.getLogger("api.timed");@Around("@annotation(org.springframework.web.bind.annotation.GetMapping)") // 拦截所有 Get 请求public Object recordExecutionTime(ProceedingJoinPoint pjp) throws Throwable {StopWatch sw = new StopWatch();sw.start();Object result = pjp.proceed(); // 执行原方法sw.stop();logger.info("**方法【{}】耗时: {}ms**", pjp.getSignature(), sw.getTotalTimeMillis());return result;}
}
注解:
- @Around 注解拦截所有 GetMapping 方法,零侵入。
- 通过 ProceedingJoinPoint 获取方法签名,精准定位慢接口。
- 缺点:无法监控非 Spring 管理的类(如手动 new 的对象)。
方案 3:拦截器(Controller 层统一监控)
代码:
public class TimedInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {request.setAttribute("startTime", System.currentTimeMillis()); // 记录开始时间return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {long startTime = (long) request.getAttribute("startTime");long cost = System.currentTimeMillis() - startTime;System.out.printf("**请求【%s】耗时: %dms**%n", request.getRequestURI(), cost);}
}@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TimedInterceptor()).addPathPatterns("/api/**"); // 拦截所有 /api 下的请求}
}
注解:
- preHandle 在请求前记录时间,afterCompletion 在请求后计算耗时。
- 只适用于 Controller 层,无法监控 Service/DAO 层方法。
- 配置简单,适合 Web 项目快速接入。
方案 4:Filter(Servlet 级通用监控)
代码:
@Component
public class RequestTimingFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(RequestTimingFilter.class);@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;long startTime = System.nanoTime(); // 高精度计时try {chain.doFilter(request, response); // 继续处理请求} finally {long duration = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);logger.info("**[{}] {} - {}ms (Status: {})**",httpRequest.getMethod(),httpRequest.getRequestURI(),duration,((HttpServletResponse) response).getStatus());}}
}
注解:
- 全局生效,所有请求(包括静态资源)都会被监控。
- 粒度较粗,无法定位具体方法耗时。
- 可通过 excludePaths 过滤不需要监控的 URI。
方案 5:事件监听(零侵入全局统计)
代码:
@Component
public class TimedListener {@EventListener(ServletRequestHandledEvent.class)public void recordTimed(ServletRequestHandledEvent event) {System.err.println("**请求监控事件: " + event + "**");}
}
注解:
- Spring 内部事件机制,无需任何配置。
- 只能获取 总耗时,无法拆分各阶段耗时。
- 适合 快速接入,不适合精细化监控。
方案 6:Micrometer + Prometheus(可视化监控)
代码:
@RestController
public class ApiController {@Timed(value = "api.query", description = "查询业务接口") // 关键注解@GetMapping("/query")public ResponseEntity<String> query() throws Exception {TimeUnit.MILLISECONDS.sleep(new Random().nextLong(2000));return ResponseEntity.ok("api query...");}
}
配置:
# application.yml
management:endpoints:web:exposure:include: prometheus # 暴露 Prometheus 端点metrics:export:prometheus:enabled: true
Prometheus 配置:- job_name: "spring-boot-app"metrics_path: "/actuator/prometheus"static_configs:- targets: ["localhost:8080"]
注解:
- @Timed 注解 零侵入,自动记录耗时指标。
- Prometheus + Grafana 可视化展示,支持 报警规则。
- 缺点:需引入额外依赖,适合生产环境。
方案 7:SkyWalking(分布式全链路追踪)
启动命令:
java -javaagent:/path/skywalking-agent.jar \-Dskywalking.agent.service_name=your-app \-jar your-app.jar
注解:
- 无代码侵入,通过 Java Agent 自动注入。
- 支持 分布式链路追踪,跨服务追踪耗时。
- 适合微服务架构,强烈推荐!
如何选?
• 单体应用:Micrometer + Prometheus(可视化 + 报警)。
• 微服务架构:SkyWalking(全链路追踪)。
• 临时调试:Arthas(在线诊断神器)。