javassist库小实例

我们常用到的动态特性主要是反射,在运行时查找对象属性、方法,修改作用域,通过方法名称调用方法等。但反射的性能开销较大,Javassit是一个东京研究院开发的第三方库,提供了运行时操作Java字节码的方法。        类似字节码操作方法还有ASM,几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM。

package fanshe;

public class Person extends China implements Student{
	private int sex;

	public int getSex() {
		return sex;
	}

	public void setSex(int sex) {
		this.sex = sex;
	}
	
	public String sayHello(String a,String b) throws Exception{
		System.out.println(a+b);
		return a+b;
	}
	
	public void test(){
		for (int i=0;i<1000000;i++) {
			
		}
		System.out.println("test");
	}
	
}

【实例1】

private static void timeFun() throws Exception {
	CtClass ctClass = ClassPool.getDefault().get("fanshe.Person");
	String mname = "test";        
	    CtMethod mold = ctClass.getDeclaredMethod(mname);
	    
	    //修改原有的方法名称
        String nname = mname + "$impl";
        mold.setName(nname);
         //创建新的方法,复制原来的方法
        CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);
         //主要的注入代码
        StringBuffer body = new StringBuffer();
        body.append("{\nlong start = System.currentTimeMillis();\n");
        //调用原有代码,类似于method();($$)表示所有的参数
        body.append(nname + "($$);\n");
        body.append("System.out.println(\"Call to method "
                    + mname
                    + " took \" +\n (System.currentTimeMillis()-start) + "
                    + "\" ms.\");\n");
       
        body.append("}");
         //替换新方法
        mnew.setBody(body.toString());
         //增加新方法
        ctClass.addMethod(mnew);
        //类已经更改,注意不能使用A a=new A();,因为在同一个classloader中,不允许装载同一个类两次
        Person a=(Person)ctClass.toClass().newInstance();
        a.test();
}

【实例2】

private static void inserFun() throws Exception{
	ClassPool pool = ClassPool.getDefault();  
	CtClass ctClass = pool.get("fanshe.Person");
	
	CtMethod ctm = ctClass.getDeclaredMethod("sayHello");  
	ctm.insertBefore("{System.out.println(\"i=\"+($1)+\",j=\"+$2);}");  
     ctClass.writeFile();//这里我不知道为什么写不到文件里,很纳闷。  
        
     Method m = ctClass.toClass().getMethod("sayHello",java.lang.String.class,java.lang.String.class);  
     Person s = new Person();  
     m.invoke(s, "a","b"); 

}

补充:可以通过javassist动态获取类方法中的参数列表(反射做不到这一点)

static void javassistGetInfo() throws Exception{  
         Class<?> clazz = Class.forName("fanshe.Person");  
         ClassPool pool = ClassPool.getDefault();    
         CtClass cc = pool.get(clazz.getName());    
           
         Method[] declaredMethods = clazz.getDeclaredMethods();  
         for (Method mt:declaredMethods) {  
             String modifier = Modifier.toString(mt.getModifiers());  
             Class<?> returnType = mt.getReturnType();  
             String name = mt.getName();  
             Class<?>[] parameterTypes = mt.getParameterTypes();  
               
             System.out.print("\n"+modifier+" "+returnType.getName()+" "+name+" (");  
               
               
             //CtMethod[] declaredMethods1 = cc.getDeclaredMethods();  
             CtMethod ctm = cc.getDeclaredMethod(name);  
             MethodInfo methodInfo = ctm.getMethodInfo();  
             CodeAttribute codeAttribute = methodInfo.getCodeAttribute();  
             LocalVariableAttribute attribute = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag);  
             int pos = Modifier.isStatic(ctm.getModifiers()) ? 0 : 1;  
             for (int i=0;i<ctm.getParameterTypes().length;i++) {  
                 System.out.print(parameterTypes[i]+" "+attribute.variableName(i+pos));  
                 if (i<ctm.getParameterTypes().length-1) {  
                     System.out.print(",");  
                 }  
             }  
               
             System.out.print(")");  
               
             Class<?>[] exceptionTypes = mt.getExceptionTypes();  
             if (exceptionTypes.length>0) {  
                    System.out.print(" throws ");  
                    int j=0;  
                    for (Class<?> cl:exceptionTypes) {  
                        System.out.print(cl.getName());  
                        if (j<exceptionTypes.length-1) {  
                            System.out.print(",");  
                        }  
                        j++;  
                    }  
                }  
         }  
           
    }





你可能感兴趣的:(AOP,反射,javassist)