SpringBoot实战:七种统计方法耗时的实现方式

简介: 在Spring Boot开发中,统计方法执行时间是性能优化的重要手段。本文介绍了七种实现方法耗时统计的技巧,包括手动使用StopWatch、AOP全局监控、自定义注解+切面、拦截器、Filter、Actuator+Micrometer集成以及事件监听等方式。每种方法适用于不同场景,开发者可根据需求选择合适的方案,从而更高效地定位性能瓶颈并提升系统响应速度。

作为开发者,我们经常需要统计方法的执行时间,以便找出性能瓶颈,优化系统响应速度。今天分享在SpringBoot框架中实现方法耗时统计的几种方法。

一、手动使用StopWatch

最直接的方法是使用Spring提供的StopWatch类,这种方式简单直观,适合临时性的性能测试。

java

体验AI代码助手

代码解读

复制代码

import org.springframework.util.StopWatch;

@Service
public class UserService {
    
    public User findUserById(Long id) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        // 业务逻辑
        User user = userRepository.findById(id).orElse(null);
        
        stopWatch.stop();
        System.out.println("findUserById方法耗时:" + stopWatch.getTotalTimeMillis() + "ms");
        
        return user;
    }
}

优点:简单直观,无需额外配置

缺点:侵入业务代码,不够优雅,需要手动添加到每个需要监控的方法

二、使用AOP实现全局方法耗时统计

AOP(面向切面编程)是实现方法耗时统计的理想选择,它可以在不修改原有代码的情况下,统一处理耗时统计逻辑。

首先,添加AOP依赖:

xml

体验AI代码助手

代码解读

复制代码

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后,创建切面类:

java

体验AI代码助手

代码解读

复制代码

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Aspect
@Component
public class MethodTimeAspect {
    
    @Pointcut("execution(* com.example.demo.service.*.*(..))")
    public void serviceMethodPointcut() {}
    
    @Around("serviceMethodPointcut()")
    public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        // 执行目标方法
        Object result = joinPoint.proceed();
        
        stopWatch.stop();
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法[" + methodName + "]耗时:" + stopWatch.getTotalTimeMillis() + "ms");
        
        return result;
    }
}

优点:代码无侵入,统一管理,配置灵活

缺点:对于特定方法的定制化需求不够灵活

三、自定义注解+AOP实现更精细的控制

这种方法结合了自定义注解和AOP,可以更精确地控制哪些方法需要进行耗时统计。

首先,创建自定义注解:

java

体验AI代码助手

代码解读

复制代码

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimeLog {
    String value() default "";
}

然后,创建切面类处理带有该注解的方法:

ini

体验AI代码助手

代码解读

复制代码

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Aspect
@Component
public class TimeLogAspect {
    
    @Around("@annotation(com.example.demo.annotation.TimeLog)")
    public Object timeLogAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        TimeLog timeLog = signature.getMethod().getAnnotation(TimeLog.class);
        
        String methodDesc = timeLog.value().isEmpty() ? 
                signature.getMethod().getName() : timeLog.value();
        
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        Object result = joinPoint.proceed();
        
        stopWatch.stop();
        System.out.println("方法[" + methodDesc + "]耗时:" + stopWatch.getTotalTimeMillis() + "ms");
        
        return result;
    }
}

使用示例:

kotlin

体验AI代码助手

代码解读

复制代码

@Service
public class ProductService {
    
    @TimeLog("查询商品详情")
    public Product getProductDetail(Long id) {
        // 业务逻辑
        return productRepository.findById(id).orElse(null);
    }
}

优点:更精细的控制,注解可携带更多信息,便于定制

缺点:需要手动在方法上添加注解

四、使用拦截器统计Controller接口耗时

如果只关注Controller层的接口耗时,可以使用Spring的拦截器:

typescript

体验AI代码助手

代码解读

复制代码

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class ApiTimeInterceptor implements HandlerInterceptor {
    
    private ThreadLocal<Long> startTime = new ThreadLocal<>();
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        startTime.set(System.currentTimeMillis());
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime.get();
        String uri = request.getRequestURI();
        System.out.println("接口[" + uri + "]耗时:" + executionTime + "ms");
        startTime.remove();
    }
}

注册拦截器:

kotlin

体验AI代码助手

代码解读

复制代码

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    private final ApiTimeInterceptor apiTimeInterceptor;
    
    public WebConfig(ApiTimeInterceptor apiTimeInterceptor) {
        this.apiTimeInterceptor = apiTimeInterceptor;
    }
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(apiTimeInterceptor).addPathPatterns("/api/");
    }
}

优点:专注于Web接口性能,对接口进行统一监控

缺点:只能监控Controller层方法,无法监控内部服务方法

五、使用Actuator + Micrometer实现细粒度监控

Spring Boot Actuator提供了与Micrometer的集成,可以实现更专业的性能指标收集:

添加依赖:

xml

体验AI代码助手

代码解读

复制代码

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

使用Micrometer进行方法计时:

java

体验AI代码助手

代码解读

复制代码

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    
    private final MeterRegistry meterRegistry;
    
    public OrderService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    public Order createOrder(OrderRequest request) {
        Timer.Sample sample = Timer.start(meterRegistry);
        
        // 业务逻辑
        Order order = processOrder(request);
        
        sample.stop(meterRegistry.timer("order.creation.time"));
        
        return order;
    }
}

配置Actuator暴露指标:

yaml

体验AI代码助手

代码解读

复制代码

management:
  endpoints:
    web:
      exposure:
        include: metrics,prometheus
  metrics:
    export:
      prometheus:
        enabled: true

优点:专业的性能指标收集,可与Prometheus、Grafana等监控系统集成,适合生产环境

缺点:配置相对复杂,有一定学习成本

六、使用Filter实现请求耗时统计

创建一个Filter实现类,可以记录每次HTTP请求的开始时间和结束时间,从而计算出请求的整体耗时。

java

体验AI代码助手

代码解读

复制代码

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

@Component
public class TimingFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        long startTime = System.currentTimeMillis();
        
        // 继续处理请求
        chain.doFilter(request, response);
        
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        String requestUri = ((HttpServletRequest) request).getRequestURI();
        System.out.println("请求[" + requestUri + "]耗时:" + executionTime + "ms");
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    
    @Override
    public void destroy() {}
}

优点:可以全局监控所有Web请求的耗时。

缺点:只提供整体请求的耗时,无法深入到具体业务逻辑的执行时间。

七、使用ServletRequestHandledEvent统计请求处理耗时

Spring Boot提供了ServletRequestHandledEvent事件,可以用来监控HTTP请求的处理时间。这种方式适合于全局监控所有的请求。

首先,创建事件监听器:

typescript

体验AI代码助手

代码解读

复制代码

import org.springframework.context.ApplicationListener;
import org.springframework.web.context.request.ServletRequestHandledEvent;
import org.springframework.stereotype.Component;

@Component
public class RequestTimingListener implements ApplicationListener<ServletRequestHandledEvent> {

    @Override
    public void onApplicationEvent(ServletRequestHandledEvent event) {
        System.out.println("请求[" + event.getRequestUrl() + "]耗时:" + event.getProcessingTimeMillis() + "ms");
    }
}

这种方法会自动监听处理结果,不需要在每个Controller中进行显式的耗时统计。

优点:不需要修改现有代码,监控全局请求的耗时

缺点:不支持自定义请求的粒度控制

总结与对比

在SpringBoot中,以上七种方法各有优缺点,可以根据不同的场景选择合适的方案:

  1. StopWatch手动统计:适合临时测试,快速实现
  2. 全局AOP:适合对整个服务层进行性能监控
  3. 自定义注解+AOP:适合精细化控制,只监控关键方法
  4. 拦截器:适合Web接口监控
  5. Actuator+Micrometer:适合生产环境,与专业监控系统集成
  6. Filter:适合全局请求监控,轻量级实现
  7. ServletRequestHandledEvent:全局监控HTTP请求处理时间,不需改动代码


转载来源:https://juejin.cn/post/7486322280861679670

相关文章
|
7月前
|
Java API Spring
Java小抄 使用StopWatch输出执行耗时
通过本文的介绍,我们详细讲解了如何使用 `StopWatch` 类测量代码执行时间。`StopWatch` 提供了简单而强大的功能,帮助我们精确分析代码的性能瓶颈,优化程序效率。希望本文能帮助您更好地理解和应用 `StopWatch`,在实际开发中提高代码性能和质量。
1126 80
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
1070 2
|
3月前
|
XML 人工智能 Java
优化SpringBoot程序启动速度
本文介绍了三种优化SpringBoot启动速度的方法:1) 延迟初始化Bean,通过设置`spring.main.lazy-initialization`为true,将耗时操作延后执行;2) 创建扫描索引,利用`spring-context-indexer`生成@ComponentScan的索引文件,加速类扫描过程;3) 升级至最新版SpringBoot,享受官方性能优化成果。这些方法能显著提升程序编译与启动效率。
1010 0
|
2月前
|
消息中间件 存储 Java
第15课: Spring Boot中集成ActiveMQ
第15课: Spring Boot中集成ActiveMQ
323 0
|
3月前
|
人工智能 JSON 安全
Spring Boot实现无感刷新Token机制
本文深入解析在Spring Boot项目中实现JWT无感刷新Token的机制,涵盖双Token策略、Refresh Token安全性及具体示例代码,帮助开发者提升用户体验与系统安全性。
391 5
|
2月前
|
canal 数据可视化 关系型数据库
2025年5大国产ETL工具横向评测
在企业数据管理中,ETL工具成为整合分散数据的关键。本文介绍了五款主流国产ETL工具:FineDataLink(低代码、功能全面)、Kettle(开源易用)、DataX(高速同步)、Canal(MySQL实时增量处理)和StreamSets(可视化强),帮助用户根据需求选择最合适的工具,提升数据效率与业务价值。
|
3月前
|
Prometheus 监控 Cloud Native
Spring Boot 可视化监控
本文介绍了如何通过Spring Actuator、Micrometer、Prometheus和Grafana为Spring Boot应用程序添加监控功能。首先创建了一个Spring Boot应用,并配置了Spring Actuator以暴露健康状态和指标接口。接着,利用Micrometer收集应用性能数据,并通过Prometheus抓取这些数据进行存储。最后,使用Grafana将Prometheus中的数据可视化,展示在精美的仪表板上。整个过程简单易行,为Spring Boot应用提供了基本的监控能力,同时也为后续扩展更详细的监控指标奠定了基础。
674 2
|
Java Spring
spring boot 中默认最大线程连接数,线程池数配置查看
spring boot 中默认最大线程连接数,线程池数配置查看
814 4
|
缓存 开发框架 Java
如何优化Spring Boot应用的启动时间?
如何优化Spring Boot应用的启动时间?
|
Prometheus 监控 Cloud Native
Spring Boot中使用Micrometer进行指标监控
Spring Boot中使用Micrometer进行指标监控