javassist学习

最近学习了javassist的使用方法。 
javassist是一个字节码类库,可以用他来动态生成类,动态修改类等等。 

下面是如果用javassist来动态创建一个类的demol 

我们需要创建的目标类,如下: 

Java代码  收藏代码
  1. public class JavassistClass{  
  2.     private String name="default";  
  3.     public JavassistClass(){  
  4.         name="me";  
  5.     }  
  6.         public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public void execute(){  
  13.         System.out.println(name);  
  14.         System.out.println("execute ok");  
  15.     }  
  16. }  



如下为用javassist来创建类的代码: 

Java代码  收藏代码
  1. import java.lang.reflect.Method;  
  2. import java.lang.reflect.Modifier;  
  3.   
  4. import javassist.ClassPool;  
  5. import javassist.CtClass;  
  6. import javassist.CtConstructor;  
  7. import javassist.CtField;  
  8. import javassist.CtField.Initializer;  
  9. import javassist.CtMethod;  
  10. import javassist.CtNewMethod;  
  11.   
  12. public class JavassistLearn{  
  13.       
  14.       
  15.     public static void main(String[] args) throws Exception{  
  16.         ClassPool cp=ClassPool.getDefault();  
  17.         CtClass ctClass=cp.makeClass("com.slovef.JavassistClass");  
  18.           
  19.         StringBuffer body=null;  
  20.         //参数  1:属性类型  2:属性名称  3:所属类CtClass  
  21.         CtField ctField=new CtField(cp.get("java.lang.String"), "name", ctClass);  
  22.         ctField.setModifiers(Modifier.PRIVATE);  
  23.         //设置name属性的get set方法  
  24.         ctClass.addMethod(CtNewMethod.setter("setName", ctField));  
  25.         ctClass.addMethod(CtNewMethod.getter("getName", ctField));  
  26.         ctClass.addField(ctField, Initializer.constant("default"));  
  27.           
  28.         //参数  1:参数类型   2:所属类CtClass  
  29.         CtConstructor ctConstructor=new CtConstructor(new CtClass[]{}, ctClass);  
  30.         body=new StringBuffer();  
  31.         body.append("{\n name=\"me\";\n}");  
  32.         ctConstructor.setBody(body.toString());  
  33.         ctClass.addConstructor(ctConstructor);  
  34.           
  35.         //参数:  1:返回类型  2:方法名称  3:传入参数类型  4:所属类CtClass  
  36.         CtMethod ctMethod=new CtMethod(CtClass.voidType,"execute",new CtClass[]{},ctClass);  
  37.         ctMethod.setModifiers(Modifier.PUBLIC);  
  38.         body=new StringBuffer();  
  39.         body.append("{\n System.out.println(name);");  
  40.         body.append("\n System.out.println(\"execute ok\");");  
  41.         body.append("\n return ;");  
  42.         body.append("\n}");  
  43.         ctMethod.setBody(body.toString());  
  44.         ctClass.addMethod(ctMethod);  
  45.         Class<?> c=ctClass.toClass();  
  46.         Object o=c.newInstance();  
  47.         Method method=o.getClass().getMethod("execute", new Class[]{});  
  48.         //调用字节码生成类的execute方法  
  49.         method.invoke(o, new Object[]{});  
  50.     }  
  51.   
  52. }  




javassist还有一个比较常见的用途是AOP,比如对一些类统一加权限过滤,加日志监控等等。 
下面示例如何使用javassist来进行AOP拦截处理 

我们对上面例子的JavassistClass类的getName()方法进行拦截前置处理 

Java代码  收藏代码
    1. package com.taobao.relationrecommend.web.util;  
    2.   
    3. import java.lang.reflect.Method;  
    4.   
    5. import javassist.util.proxy.MethodFilter;  
    6. import javassist.util.proxy.MethodHandler;  
    7. import javassist.util.proxy.ProxyFactory;  
    8.   
    9. public class JavassistLearn{  
    10.       
    11.       
    12.     public static void main(String[] args) throws Exception{  
    13.         ProxyFactory factory=new ProxyFactory();  
    14.         //设置父类,ProxyFactory将会动态生成一个类,继承该父类  
    15.         factory.setSuperclass(JavassistClass.class);  
    16.         //设置过滤器,判断哪些方法调用需要被拦截  
    17.         factory.setFilter(new MethodFilter() {  
    18.             @Override  
    19.             public boolean isHandled(Method m) {  
    20.                 if(m.getName().equals("getName")){  
    21.                     return true;  
    22.                 }  
    23.                 return false;  
    24.             }  
    25.         });  
    26.         //设置拦截处理  
    27.         factory.setHandler(new MethodHandler() {  
    28.             @Override  
    29.             public Object invoke(Object self, Method thisMethod, Method proceed,  
    30.                     Object[] args) throws Throwable {  
    31.                 //拦截后前置处理,改写name属性的内容  
    32.                 //实际情况可根据需求修改  
    33.                 JavassistClass o=(JavassistClass) self;  
    34.                 o.setName("haha");  
    35.                 return proceed.invoke(self, args);  
    36.             }  
    37.         });  
    38.           
    39.         Class<?> c=factory.createClass();  
    40.         JavassistClass object=(JavassistClass) c.newInstance();  
    41.         System.out.println(object.getName());  
    42.           
    43.     }  
    44.   
    45. }  
posted @ 2015-05-10 20:07  一粒沙的世界  阅读(858)  评论(0编辑  收藏  举报