`
deepnighttwo
  • 浏览: 49566 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Javasssist初探(需要对Java的ClassLoader机制有一些了解)

 
阅读更多

Javassist可以用来动态生成java类,就好像js可以生成可执行的js代码一样。javassist是JBoss的一个子项目,用处的话可能是在对EJB提供支持的时候,将声称各种接口的实现类和代理类。

下面给出一个例子,在这个例子中一共有三个类:DirectLoader自定义类加载器;IAccess是接口类(我们动态生成的类要实现这个接口);MainTest完成主要逻辑的类,其中javassist的使用也在这里面体现。下面给出三个类的源代码。需要使用javassist的jar包程序才能运行



//--------------DirectLoader------------------------------------
importjava.security.SecureClassLoader;

publicclassDirectLoaderextendsSecureClassLoader...{
protectedDirectLoader()...{

super(MainTest.class.getClassLoader());
}


protectedClassload(Stringname,byte[]data)...{
returnsuper.defineClass(name,data,0,data.length);
}

}



//--------------IAccess------------------------------------
importjava.util.List;

publicinterfaceIAccess...{
publicvoidCalculate(ListInVars)throwsException;
}



//--------------MainTest------------------------------------

importjava.util.List;

importjavassist.ClassPool;
importjavassist.CtClass;
importjavassist.CtConstructor;
importjavassist.CtMethod;

/**//*
*本类用来演示如何使用javassist动态生成
*/


publicclassMainTest...{
privatestaticfinalCtClass[]NO_ARGS=...{};

//privatestaticfinalCtClass[]INT_ARGS={CtClass.intType};

privatestaticbooleanisFirst=true;

//用这个标示标记是否需要重新生成新的类。
//一般情况下,我们没必要动态生成类,如果有这个必要
//就说明类需要动态改动并使用,所以,这个变量是很有用的
privatestaticbooleanneedReload=true;

privatestaticDirectLoaders_classLoader=newDirectLoader();

publicMainTest()...{
}


publicstaticvoidmain(String[]args)throwsException...{
execTest();
execTest();
}


/***//**
*执行代码
*
*
@throwsException
*/

publicstaticvoidexecTest()throwsException...{
Classclas
=null;
try...{
if(needReload)...{
clas
=createExecClass();
}
else...{
clas
=s_classLoader.loadClass("ExecVar");
}

}
catch(ClassNotFoundExceptione)...{
System.out.println(
"没有这个类,动态生成");
clas
=createExecClass();
}

//使用动态生成的类,最好是使用接口。否则就只能通过反射调用其方法了
IAccessaccess=null;
try...{
access
=(IAccess)clas.newInstance();
}
catch(IllegalAccessExceptionex)...{
ex.printStackTrace(System.err);
System.exit(
1);
}
catch(InstantiationExceptionex)...{
ex.printStackTrace(System.err);
System.exit(
1);
}

List
<String>list=newjava.util.ArrayList<String>();
list.add(
"ThisisaString");
//通过借口的引用调用我们动态生成的类的
access.Calculate(list);
}


privatestaticClasscreateExecClass()throwsException...{
//ClassPool是javasssit中的类,作用嘛,自描述的
ClassPoolpool=ClassPool.getDefault();
CtClassclas
=null;
if(!isFirst)...{
//如果不是第一次,就必须要将原来的类在pool中作废,
//否则无法在同一个pool中生成新的类
//具体做法是否正确,有待进一步考证
pool=ClassPool.getDefault();
clas
=pool.get("ExecVar");
if(clas.isFrozen())...{
System.out
.println(
"ClassExecVarisfrozen,Pleaselookingforsomethingthatcanmakeitunfrozen!");
//clas.defrost();
//从pool中拆离这个类
clas.detach();
}

}

isFirst
=false;

//动态生成一个类
clas=pool.makeClass("ExecVar");
clas.addInterface(pool.get(
"IAccess"));
//增加默认的构造方法
CtConstructorcons=newCtConstructor(NO_ARGS,clas);
cons.setBody(
";");
clas.addConstructor(cons);

//增加一个方法,参数为java.util.List,返回值是空,名字叫做Calculate,所属类是clas
CtMethodmeth=newCtMethod(CtClass.voidType,"Calculate",
newCtClass[]...{pool.get("java.util.List")},clas);
//用这个随机数检测是否是新生成的类
doublerandom=Math.random();
meth.setBody(
"System.out.println("这是一个reload测试:"+$1.get(0)+",随机数:"
+random+"");");
//将方法加入其中
clas.addMethod(meth);
//创建一个新的ClassLoader,以加载新的生成的类,旧的s_classLoader连同旧的
//ExecVar类一起被废弃
s_classLoader=newDirectLoader();
returns_classLoader.load("ExecVar",clas.toBytecode());
}

}




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics