【ko-time】核心代码解析笔记

ko-time是一个用于方法执行时间计算的工具,通过切面编程在方法调用前后记录时间,以分析方法执行耗时。由于其对性能的影响,主要适用于开发环境。相比之下,Skywalking更适合微服务架构。本文将探讨ko-time的关键注解和反射技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ko-time核心代码

核心逻辑就是对方法做切面,方法执行前后有start和end时间的计算,然后打印出end-start耗时
ko-time对性能有影响,并且为单体架构,只建议在开发环境使用,目前市场中常用的为skywalking,增对微服务架构

ko-time接口可参考官方文档,在这里不做说明
获取调用链路,接口方法函数数据库表耗时,在这里不做说明

关键注解如下:

是否登录注解

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

计算时间注解,可在依赖此jar后使用注解来获取耗时

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ComputeTime {
    String value() default "chinese";
}
关键反射:

反射登录注解,判断是否登录

@Aspect
@Component
public class AuthHandler {
    public static Logger log = Logger.getLogger(AuthHandler.class.toString());

    @Pointcut(KoConstant.authRange)
    public void preProcess() {
    }

    @Around("preProcess()")
    public Object doAroundCompute(ProceedingJoinPoint pjp) throws Throwable {
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        boolean needAuth = method.isAnnotationPresent(Auth.class);
        if (needAuth&& Context.getConfig().getAuthEnable()) {
            KoUtil.checkLogin();
        }
        return pjp.proceed();
    }
}

反射计算时间注解,从切面计算方法运行时间

@Aspect
@Component
public class ComputeTimeHandler {
    public static Logger log = Logger.getLogger(ComputeTimeHandler.class.toString());

    @Pointcut(KoConstant.comMethodRange)
    public void preProcess() {
    }

    @Around("preProcess()")
    public Object doAroundCompute(ProceedingJoinPoint pjp) throws Throwable {
        ComputeTime computeTime = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(ComputeTime.class);
        long begin = System.nanoTime();
        Object obj = pjp.proceed();
        long end = System.nanoTime();
        if ("chinese".equals(computeTime.value())) {
            log.info("调用方法=" + pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName() + ",耗时=" + ((end - begin) / 1000000) + "毫秒");
        } else {
            log.info("method=" + pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName() + ",runTime=" + ((end - begin) / 1000000) + "ms");
        }
        return obj;
    }
}

设置advice,将RunTimeHandler放入

    @Bean
    public AspectJExpressionPointcutAdvisor configurabledvisor() {
        log.info("kotime=>loading method listener");
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(defaultConfig.getPointcut()==null?pointcut:defaultConfig.getPointcut());
        advisor.setAdvice(new RunTimeHandler());
        return advisor;
    }

设置方法耗时,或者抛出异常,实现了方法拦截器,对方法进行切面,这是本身ko-time的接口耗时实现

public class RunTimeHandler implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        boolean kotimeEnable = Context.getConfig().getEnable();
        if (!kotimeEnable) {
            return invocation.proceed();
        }
        boolean exceptionEnable = Context.getConfig().getExceptionEnable();
        long begin = System.nanoTime();
        Object obj = null;
        MethodNode parent = InvokeService.getParentMethodNode();
        MethodStack.record(invocation);
        if (exceptionEnable) {
            try {
                obj = invocation.proceed();
            } catch (Exception e) {
                ExceptionNode exception = new ExceptionNode();
                exception.setName(e.getClass().getSimpleName());
                exception.setClassName(e.getClass().getName());
                exception.setMessage(e.getMessage());
                exception.setValue(e.getStackTrace()[0].getLineNumber());
                exception.setId(exception.getClassName() + exception.getName() + exception.getMessage());
                MethodNode current = InvokeService.getCurrentMethodNode(invocation, 0.0);
                if (current.getClassName().equals(e.getStackTrace()[0].getClassName())) {
                    GraphService graphService = GraphService.getInstance();
                    graphService.addMethodNode(current);
                    graphService.addExceptionNode(exception);
                    graphService.addExceptionRelation(current, exception);
                }
                MethodStack.clear();
                throw e;
            }
        } else {
            obj = invocation.proceed();
        }
        long end = System.nanoTime();
        MethodNode current = InvokeService.getCurrentMethodNode(invocation, ((end - begin) / 1000000.0));
        GraphService graphService = GraphService.getInstance();
        graphService.addMethodNode(parent);
        graphService.addMethodNode(current);
        graphService.addMethodRelation(parent, current);
        MethodStack.clear();
        return obj;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值