今天在看Thinking in Java的时候,配置工程出现错误:
java: 程序包javassist不存在
原因就像错误描述的那样,缺少javassist.jar包。本来应该是不值一提的错误,但是hankcs还是初次接触这个javassist.jar,还是得查查做个memo。它是JBoss的一个子项目,可以直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。你可以在这里下载到。这玩意儿可真是个狠家伙,可以动态生成\注入代码,修改已有的代码。令我回忆起windows上的线程注入dll注入了。
Talking is cheap,show me the code:-D
假设我有一个class A
package com.hankcs;
import java.util.Arrays;
/**
* @author Hankcs
*/
public class A
{
private int[] a = new int[]{23, 35, 46, 12, 99, 48, 74};
public void foo(int n)
{ //示意性的代码表示业务逻辑
for (int i = 0; i < n; i++)
{
Arrays.sort(a);
}
System.out.println("class A.foo()");
}
}
我想要在程序中动态改变A的代码,利用javassist.jar可以轻易做到:
package com.hankcs;
import javassist.*;
public class Main
{
public static void main(String[] args) throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException
{
// 获取com.hankcs.A这个类
CtClass cc = ClassPool.getDefault().get("com.hankcs.A");
// 获取A类中的foo方法
CtMethod method = cc.getDeclaredMethod("foo");
// 重新取个名字,待会儿还要调用
method.setName("foo$impl");
// 将foo方法复制出一个新的方法,新方法与元方法一摸一样
CtMethod newMethod = CtNewMethod.copy(method, "foo", cc, null);
// 用字串写动态代码
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" long start = System.currentTimeMillis();\n");
sb.append(" foo$impl($$);\n");
sb.append(" long end = System.currentTimeMillis();\n");
sb.append(" System.out.println(\"Time interval = \" + (end - start) + \"ms\");\n");
sb.append("}\n");
// 将动态代码设为newMethod的Body
newMethod.setBody(sb.toString());
// 动态加入到类
cc.addMethod(newMethod);
// 生成实例
A a = (A) cc.toClass().newInstance();
// 输出Time interval =
a.foo(10000000);
// 依然输出Time interval =
A b = new A();
b.foo(10000000);
}
}
输出:
class A.foo() Time interval = 244ms class A.foo() Time interval = 192ms Process finished with exit code 0
工程下载:http://pan.baidu.com/s/1BsHRh

参考http://hi.baidu.com/jackfrued/item/be340ce278b5daa8c10d75a1
码农场