首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

应用javassist动态注入代码

2012-10-29 
使用javassist动态注入代码使用javassist动态注入代码??? 关于java字节码的处理,目前有很多工具,如bcel,as

使用javassist动态注入代码

使用javassist动态注入代码

??? 关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。?
??? 下面通过一个简单的例子,通过javassist来实现如何动态注入代码。?
??? 假设,存在类A,如下:

java 代码

  1. public class A {?
  2. public void method() {?
  3. for (int i = 0; i < 1000000; i++) {?
  4. ??????? }?
  5. ??????? System.out.println("method1");?
  6. ??? }?
  7. }?

测试类B如下:

java 代码

  1. public class B {?
  2. public static void main(String[] args) {?
  3. ??????? A a = new A();?
  4. ??????? a.method();????
  5. ??? }?
  6. }?

现在想统计一下method的执行时间,?
默认的实现是修改method:

java 代码

  1. public void method() {?
  2. long start = System.currentTimeMillis();?
  3. for (int i = 0; i < 1000000; i++) {?
  4. ??????? }?
  5. ??????? System.out.println("method1");?
  6. long end = System.currentTimeMillis();?
  7. ??????? System.out.println(end - start);?
  8. ??? }?

如果A的方法很多,统计方法的执行时间的代码就会相应的增加。为了减少工作量,通过动态注入代码的形式来实现。?
修改B的main方法:

java 代码

  1. public static void main(String[] args) throws Exception {?
  2. //用于取得字节码类,必须在当前的classpath中,使用全称
  3. ????? CtClass ctClass = ClassPool.getDefault().get("org.esoft.A");?
  4. //需要修改的方法名称
  5. ????? String mname = "method";????????
  6. ????? CtMethod mold = ctClass.getDeclaredMethod(mname);?
  7. //修改原有的方法名称
  8. ????? String nname = mname + "$impl";?
  9. ????? mold.setName(nname);?
  10. //创建新的方法,复制原来的方法
  11. ????? CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);?
  12. //主要的注入代码
  13. ????? StringBuffer body = new StringBuffer();?
  14. ????? body.append("{\nlong start = System.currentTimeMillis();\n");?
  15. //调用原有代码,类似于method();($$)表示所有的参数
  16. ????? body.append(nname + "($$);\n");?
  17. ????? body.append("System.out.println("Call to method "
  18. ????????????????? + mname?
  19. ????????????????? + " took " +\n (System.currentTimeMillis()-start) + "
  20. ????????????????? + "" ms.");\n");?
  21. ????? body.append("}");?
  22. //替换新方法
  23. ????? mnew.setBody(body.toString());?
  24. //增加新方法
  25. ????? ctClass.addMethod(mnew);?
  26. //类已经更改,注意不能使用A a=new A();,因为在同一个classloader中,不允许装载同一个类两次
  27. ????? A a=(A)ctClass.toClass().newInstance();?
  28. ????? a.method();?
  29. ? }?

这只是简单的一个应用。javassist还提供了很多的功能,用于更改类结构。有兴趣的可以参考相关文档

热点排行