`
zhaohaolin
  • 浏览: 1011639 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

使用javassist动态注入代码-OO-Java

    博客分类:
  • JAVA
阅读更多

官方主页:http://www.csg.is.titech.ac.jp/~chiba/javassist/

Javassist Cglib 等是一些代码增强工具,在运行时刻进行Java字节码增强,虽然速度上稍微慢一点点,但是带来的是代码的简洁,今天用Javassist进行代码增强。

代码:

TestBean.java

 

  1. package  javassist.sample;
  2. public   abstract   class  TestBean {
  3.      public  String field;
  4.      public   abstract  String getM();
  5.      public   abstract   void  setF(String f);
  6.      public  String getF() {
  7.          return   this .field;
  8.     }
  9. }

TestByteCode.java

 

  1. package  javassist.sample;
  2. import  javassist.ClassPool;
  3. import  javassist.CtClass;
  4. import  javassist.CtConstructor;
  5. import  javassist.CtMethod;
  6. public   class  TestByteCode {
  7.      public   static   void  main(String[] args)  throws  Exception {
  8.         
  9.         ClassPool pool = ClassPool.getDefault();
  10.         CtClass pt = pool.makeClass( "asdf" , pool.get( "javassist.sample.TestBean" ));
  11.         CtMethod method1 =  new  CtMethod(pool.get( "java.lang.String" ),  "getM" null , pt);
  12.         method1.setBody( "{return \"你好\";}" );
  13.         pt.addMethod(method1);
  14.         CtConstructor cc =  new  CtConstructor( null , pt);
  15.         cc.setBody( "this.field=\"why?\";" );
  16.         pt.addConstructor(cc);
  17.         CtMethod method2 =  new  CtMethod(CtClass.voidType,  "setF" ,
  18.                  new  CtClass[] { pool.get( "java.lang.String" ) }, pt);
  19.         method2.setBody( "{this.field=$1;}" );
  20.         pt.addMethod(method2);
  21.         Class<?> c = pt.toClass();
  22.         TestBean bean = (TestBean) c.newInstance();
  23.         System.out.println(bean.getM());
  24.         System.out.println(bean.getF());
  25.         bean.setF( "setf" );
  26.         System.out.println(bean.getF());
  27.     }
  28. }

输出为:

你好

why?

setf

可以看到实现了动态的构造,动态实现抽象函数。在进行代码自动化项目中,能够使用字节码增强将大大提高代码的质量,和减少代码的数量。

 

再看一个例子:

A.java

 

  1. package  javassist.demo;
  2. public   class  A {
  3.      public   void  method() {
  4.          for  ( int  i =  0 ; i <  1000000 ; i++) {
  5.         }

 

关 于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.       
  22.       body.append("}" );  
  23.        //替换新方法   
  24.       mnew.setBody(body.toString());  
  25.        //增加新方法   
  26.       ctClass.addMethod(mnew);  
  27.       //类已经更改,注意不能使用A a=new A();,因为在同一个classloader中,不允许装载同一个类两次   
  28.       A a=(A)ctClass.toClass().newInstance();  
  29.       a.method();  
  30.   }  


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

 

分享到:
评论

相关推荐

    开发工具 javassist-3.21.0-GA

    开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发工具 javassist-3.21.0-GA开发...

    javassist-3.19.0-GA-API文档-中文版.zip

    赠送源代码:javassist-3.19.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.19.0-GA.pom; 包含翻译后的API文档:javassist-3.19.0-GA-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.javassist:...

    javassist-3.21.0-GA-API文档-中文版.zip

    赠送源代码:javassist-3.21.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.21.0-GA.pom; 包含翻译后的API文档:javassist-3.21.0-GA-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.javassist:...

    javassist-3.24.0-GA-API文档-中文版.zip

    赠送源代码:javassist-3.24.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.24.0-GA.pom; 包含翻译后的API文档:javassist-3.24.0-GA-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.javassist:...

    javassist-3.18.1-GA-API文档-中文版.zip

    赠送源代码:javassist-3.18.1-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.18.1-GA.pom; 包含翻译后的API文档:javassist-3.18.1-GA-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.javassist:...

    javassist-3.23.1-GA-API文档-中文版.zip

    赠送源代码:javassist-3.23.1-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.23.1-GA.pom; 包含翻译后的API文档:javassist-3.23.1-GA-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.javassist:...

    javassist-3.20.0-GA-API文档-中文版.zip

    赠送源代码:javassist-3.20.0-GA-sources.jar; 包含翻译后的API文档:javassist-3.20.0-GA-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.javassist,artifactId:javassist,version:3.20.0-...

    javassist-3.21.0-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.21.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.21.0-GA.pom; 包含翻译后的API文档:javassist-3.21.0-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.20.0-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.20.0-GA-sources.jar 包含翻译后的API文档:javassist-3.20.0-GA-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.javassist,artifactId:javassist,version:...

    javassist-3.27.0-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.27.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.27.0-GA.pom; 包含翻译后的API文档:javassist-3.27.0-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.18.1-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.18.1-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.18.1-GA.pom; 包含翻译后的API文档:javassist-3.18.1-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.24.0-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.24.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.24.0-GA.pom; 包含翻译后的API文档:javassist-3.24.0-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.19.0-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.19.0-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.19.0-GA.pom; 包含翻译后的API文档:javassist-3.19.0-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.23.1-GA-API文档-中英对照版.zip

    赠送源代码:javassist-3.23.1-GA-sources.jar; 赠送Maven依赖信息文件:javassist-3.23.1-GA.pom; 包含翻译后的API文档:javassist-3.23.1-GA-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    javassist-3.18.1-GA.jar

    `javassist-3.18.1-GA.jar`是Javaassist的一个特定版本,GA代表“General Availability”,意味着这是一个正式发布的稳定版本。这个版本号`3.18.1`表明它是对之前版本的改进和增强,修复了已知问题并可能引入了一些...

    javassist-3.18.2-GA.jar

    javassist-3.18.2-GA.jar

    javassist-3.27.0-GA.jar

    javassist-3.27.0-GA.jar

    javassist-3.15.0-GA

    总结来说,"javassist-3.15.0-GA"是Java开发中的一个重要工具,它使得在运行时动态修改和增强Java代码成为可能,广泛应用于AOP、动态代理、代码生成等领域。通过深入理解和熟练运用Javaassist,开发者可以提高代码的...

    jboss-javassist-javassist-rel_3_23_0_ga-2-gf85a72b

    这个名为 "jboss-javassist-javassist-rel_3_23_0_ga-2-gf85a72b" 的压缩包包含了 Javaassist 库的一个特定版本,即 3.23.0 GA 版本的修订版 gf85a72b。在 Java 开发中,Javaassist 提供了一种简单的方法来创建和...

    javassist-3.18.0-ga

    6. **兼容性**:`javassist-3.18.0-ga`版本支持Java 5及以上版本,这意味着它可以广泛应用于各种Java项目,包括那些基于旧版JDK的项目。 7. **应用领域**:Javaassist常用于动态代理框架(如Spring AOP)、代码生成...

Global site tag (gtag.js) - Google Analytics