public class MyTransformer implementsClassFileTransformer {final static String prefix = "\nlong startTime = System.currentTimeMillis();\n";final static String postfix = "\nlong endTime = System.currentTimeMillis();\n";//被处理的方法列表
final static Map> methodMap = new HashMap>();publicMyTransformer() {
add("com.hwtest.demo.MyProgram.sayHello");
add("com.hwtest.demo.MyProgram.sayHello2");
}private voidadd(String methodString) {
String className= methodString.substring(0, methodString.lastIndexOf("."));
String methodName= methodString.substring(methodString.lastIndexOf(".") + 1);
List list =methodMap.get(className);if (list == null) {
list= new ArrayList();
methodMap.put(className, list);
}
list.add(methodName);
}
@Overridepublic byte[] transform(ClassLoader loader, String className, Class>classBeingRedefined,
ProtectionDomain protectionDomain,byte[] classfileBuffer) throwsIllegalClassFormatException {
className= className.replace("/", ".");if (methodMap.containsKey(className)) {//判断加载的class的包路径是不是需要监控的类
CtClass ctclass = null;try{
ctclass= ClassPool.getDefault().get(className);//使用全称,用于取得字节码类
for(String methodName : methodMap.get(className)) {
String outputStr= "\nSystem.out.println(\"this method " +methodName+ " cost:\" +(endTime - startTime) +\"ms.\");";
CtMethod ctmethod= ctclass.getDeclaredMethod(methodName);//得到这方法实例
String newMethodName = methodName + "$old";//新定义一个方法叫做比如sayHello$old
ctmethod.setName(newMethodName);//将原来的方法名字修改//创建新的方法,复制原来的方法,名字为原来的名字
CtMethod newMethod = CtNewMethod.copy(ctmethod, methodName, ctclass, null);//构建新的方法体
StringBuilder bodyStr = newStringBuilder();
bodyStr.append("{");
bodyStr.append(prefix);
bodyStr.append(newMethodName+ "($$);\n");//调用原有代码,类似于method();($$)表示所有的参数
bodyStr.append(postfix);
bodyStr.append(outputStr);
bodyStr.append("}");
newMethod.setBody(bodyStr.toString());//替换新方法
ctclass.addMethod(newMethod);//增加新方法
}returnctclass.toBytecode();
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}return null;
}
}