利用自定义注解,统计方法执行时间

  • Post author:
  • Post category:其他


项目中需要统计某些方法的执行时间,最简易的方式是方法执行前记录时间戳startTime,在方法结束前,用时间戳endTime-startTime得出该方法耗时。

但是为了避免无代码侵入并实现通用,于是定义一个注解,如果要统计哪个方法,只需在方法上写上注解即可,通过注解可以获取到方法的参数、方法名、返回值等等信息。

下面是一个简单的时间统计实现:



1.定义一个注解

TimeConsume

该注解有一个默认的value属性,value值为方法名或自定义的描述

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimeConsume {

	String value() default "方法";
}



2.使用Aspect定义该注解的切面

TimeConsumeAspect

定义好注解后,需要对该注解使用的类进行监听,利用Spring框架Aspect实现切面,定义环绕通知,获取到方法的参数、方法名等信息,便于统计所需。对执行方法进行异常捕获,在

finally

代码块中实现时间统计逻辑,避免方法异常无法统计。代码如下:

@Slf4j
@Component
@Aspect
public class TimeConsumeAspect {

 /**
  * 切点定义为注解@annotation(注解类路径)
  */
   @Pointcut("@annotation(com.weiller.demo.common.annotation.TimeConsume)")
    public void consume(){
    }

    @Around("consume()")
    public  <T> T around(ProceedingJoinPoint pjp) throws Throwable {
        Long startTime = System.currentTimeMillis();
   
        Object[] args = pjp.getArgs();
        T result;
        Method methodClass;
        try {

            result = (T)pjp.proceed(args);//执行方法

        }finally {
            long endTime = System.currentTimeMillis();
            Signature signature = pjp.getSignature();
            String methodName = signature.getName();
            Class<?> targetClass = pjp.getTarget().getClass();
            Class[] parameterTypes = ((MethodSignature) pjp.getSignature()).getParameterTypes();
            methodClass = targetClass.getMethod(methodName, parameterTypes);
            Annotation[] annotations = methodClass.getAnnotations();
            for (Annotation annotation : annotations){
                Class<? extends Annotation> aClass = annotation.annotationType();
                String simpleName = aClass.getSimpleName();
                if("TimeConsume".equals(simpleName)){
                    TimeConsume timeConsume = (TimeConsume) annotation;
                    String value = timeConsume.value();
                    log.info(value+"[{}] 执行耗时:{}ms",methodName,endTime-startTime);
                    break;
                }
            }

        }

        return result;
    }
}



3.测试目标方法中使用

@RestController
@RequestMapping("/test")
public class testController {

    @TimeConsume("测试")
    @GetMapping("info")
    public Object testInfo(){
        Object parse = JSONObject.parse("{\n" +
                "\t\t\"requestId\":\"\",\n" +
                "\t\t\"appId\":\"\",\n" +
                "\t\t\"nonce\":\"\",\n" +
                "\t\t\"timestamp\":12345676543,\n" +
                "\t\t\"signature\":\"\",\n" +
                "\t\t\"sjgsd\":\"61000\",\n" +
                "\t\t\"starTime\":12345676543\n" +
                "\t}");
        try {
            Thread.sleep(new Random().nextInt(100));//随机时间休眠
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return parse ;
    }
}



版权声明:本文为xiweiller原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。