【Javassist】快速入门系列02 使用Javassist实现方法执行时间统计

系列文章目录

01 在方法体的开头或结尾插入代码
02 使用Javassist实现方法执行时间统计

前言

上一章我们介绍了使用Javassist实现一个简单的Hello World程序,学会了Javassist创建类和新增方法。本章主要介绍如何使用Javassist实现一个无侵入的方法执行时间统计

引入Javassist jar包

在上一篇文章已经创建了一个maven工程并引入了javassist的jar包,如果你是第一次观看本系列文章,也可以复制以下maven依赖将jar包导入工程。

        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.28.0-GA</version>
        </dependency>

使用Javassist实现方法执行时间统计

/**
 * 【Javassist】快速入门系列02 使用Javassist实现方法执行时间统计
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/19 17:23
 */
public class Basic02ExecTime {
    public static void main(String[] args) throws Exception{
        // 获取javassist的类池
        ClassPool pool = ClassPool.getDefault();
        // 获取basic.StockService javassist的ctClass文件
        CtClass ctClass = pool.get("basic.StockService");
        // 获取声明的queryStockNum方法
        CtMethod method = ctClass.getDeclaredMethod("queryStockNum");
        // 为StockService类新增stime和etime字段
        CtField stime = new CtField(CtClass.longType, "stime", ctClass);
        CtField etime = new CtField(CtClass.longType, "etime", ctClass);
        ctClass.addField(stime);
        ctClass.addField(etime);
        // 在方法体之前插入代码
        method.insertBefore("stime = System.currentTimeMillis();");
        // 在方法体之后插入代码
        method.insertAfter("etime = System.currentTimeMillis();\n" +
                "System.out.println(\"执行时长:\"+(etime - stime)+\"毫秒\");");
        // 将类写成文件
        ctClass.writeFile();
        // 获取生成后的类文件
        Class<?> clazz = ctClass.toClass();
        // 创建新的实例
        Object obj = clazz.newInstance();
        // 获取生成后的queryStockNum方法
        Method queryStockNum = clazz.getDeclaredMethod("queryStockNum", Long.class);
        // 调用生成后的queryStockNum方法
        queryStockNum.invoke(obj,(Object) 1l);
    }
}

以上Basic02ExecTime类创建了一个main方法,该方法中首先获取javassist的类池pool,然后调用pool.get(“basic.StockService”)方法获取到basic包下的StockService类。StockService类源码如下:

/**
 * 库存业务类
 * 公众号&B站:精致的王同学
 * @author 精致的王同学
 * @date 2022/12/19 17:23
 */
public class StockService {
    public Integer queryStockNum(Long skuId) throws Exception {
        // 调用库存数量接口
        Random random = new Random();
        Long mills = Long.valueOf(random.nextInt(5)*1000);
        // 模拟接口调用耗时
        Thread.sleep(mills);
        return 0;
    }
}

该类主要模拟获取sku库存数量的逻辑。使用Thread.sleep(mills)模拟接口调用耗时。

回到BasicExecTime 的main方法中,在获取到basic.StockService的ctClass对象后,获得了其声明的queryStockNum方法的CtMethod对象。

然后通过调用new CtField(CtClass type, String name, CtClass declaring) 为StockService类声明了两个字段。其中CtField构造方法的第一个参数代表字段的类型,第二个参数代表字段名称,最后一个参数代表新增字段的CtClass对象。

声明这两个字段的原因是Javassist不允许在插入的代码块中方法方法的局部变量。

之后便是调用 method.insertBefore(“stime = System.currentTimeMillis();”); 方法在方法体前插入获取当前时间毫秒数的代码,并将其赋给变量stime 。insertBefore方法的参数为字符串类型的代码块。

最后调用 method.insertAfter(“etime = System.currentTimeMillis();\n” +
“System.out.println(“执行时长:”+(etime - stime)+“毫秒”);”);方法在方法体之后插入代码,将方法执行的时间打印在屏幕上。

剩下的代码为模拟调用javassist修改后的queryStockNum方法。输出结果为:
queryStockNum方法输出结果

总结

本篇文章介绍了使用Javassist实现方法执行时间统计,同时学习了使用Javassist在方法体的开头/结尾插入代码和为类添加字段。Javassist可以在无侵入的前提下在方法体前后加入内容,非常的方便。

说明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值