写在前面
本文看下如何实现打印方法耗时和入参。
1:程序
- 需要增强的类:
public class ApiTest1 {public Integer strToInt(String str01, String str02) {return Integer.parseInt(str01);}}
- 插桩类
package com.dahuyou.javassist.huohuo.aa;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;import java.lang.reflect.Method;public class MyDoIt extends ClassLoader {public static void main(String[] args) throws Exception {ClassPool pool = ClassPool.getDefault();// 获取类和方法CtClass ctClass = pool.get(ApiTest1.class.getName());ctClass.replaceClassName("ApiTest1", "ApiTest12");String clazzName = ctClass.getName();CtMethod ctMethod = ctClass.getDeclaredMethod("strToInt");// 定义局部变量 注意必须声明,而不能直接在代码中写int xx = 222;这种,否则会报CannotCompileException: [source error] no such field: xxxctMethod.addLocalVariable("startTime", CtClass.longType);ctMethod.addLocalVariable("incomingParameters", pool.get(Object[].class.getName()));// 方法前加强
// ctMethod.insertBefore("{ startTime = System.nanoTime(); incomingParameters = new Object[]{$1, $2}; }");ctMethod.insertBefore("{ startTime = System.nanoTime(); incomingParameters = new Object[2]; incomingParameters[0] = $1; incomingParameters[1] = $2; }");// 方法后加强,输出耗时和参数ctMethod.insertAfter("System.out.println(\"执行耗时:\" + (System.nanoTime() - startTime));");// 测试调用byte[] bytes = ctClass.toBytecode();Class<?> clazzNew = new MyDoIt().defineClass("com.dahuyou.javassist.huohuo.aa.ApiTest1", bytes, 0, bytes.length);// 反射运行测试Class aClass = clazzNew;Object obj = aClass.newInstance();Method main = aClass.getDeclaredMethod("strToInt", String.class, String.class);main.invoke(obj, "99", "87");// System.out.println("执行耗时:" + (System.nanoTime() - startTime));ctClass.writeFile();}
}
insertBefore和insertAfter分别用来在方法的开始和结束插入代码。
运行:
执行耗时:48000
Process finished with exit code 0
- 查看生成的字节码