Java 编程的动态性,第 8 部分: 用代码生成取代反射
2010-03-18 00:00:00 来源:WEB开发网public class AccessValue1 implements IAccess
{
private HolderBean m_target;
public void setTarget(Object target) {
m_target = (HolderBean)target;
}
public int getValue() {
return m_target.getValue1();
}
public void setValue(int value) {
m_target.setValue1(value);
}
}
清单 2 接口设计为针对特定类型对象的特定属性使用。这个接口使实现代码简单了 —— 在处理字节码时这总是一个优点 —— 但是也意味着实现类是非常特定的。对于要通过这个接口访问的每一种类型的对象和属性,都需要一个单独的实现类,这限制了将这种方法作为反射的一般性替代方法。如果选择只在反射性能真正成为瓶颈的情况下才使用这种技术,那么这种限制就不是一个问题。
用 Javassist 生成
用 Javassist 为 清单 2 IAccess 接口生成实现类很容易 —— 只需要创建一个实现了这个接口的新类、为目标对象引用添加一个成员变量、最后再添加一个无参构造函数和简单实现方法。清单 4 显示了完成这些步骤的 Javassist 代码,它构造一个方法调用,这个方法以目标类和 get/set 方法信息为参数、并返回所构造的类的二进制表示:
清单 4. Javassist glue 类构造
/** Parameter types for call with no parameters. */
private static final CtClass[] NO_ARGS = {};
/** Parameter types for call with single int value. */
private static final CtClass[] INT_ARGS = { CtClass.intType };
protected byte[] createAccess(Class tclas, Method gmeth,
Method smeth, String cname) throws Exception {
// build generator for the new class
String tname = tclas.getName();
ClassPool pool = ClassPool.getDefault();
CtClass clas = pool.makeClass(cname);
clas.addInterface(pool.get("IAccess"));
CtClass target = pool.get(tname);
// add target object field to class
CtField field = new CtField(target, "m_target", clas);
clas.addField(field);
// add public default constructor method to class
CtConstructor cons = new CtConstructor(NO_ARGS, clas);
cons.setBody(";");
clas.addConstructor(cons);
// add public setTarget method
CtMethod meth = new CtMethod(CtClass.voidType, "setTarget",
new CtClass[] { pool.get("java.lang.Object") }, clas);
meth.setBody("m_target = (" + tclas.getName() + ")$1;");
clas.addMethod(meth);
// add public getValue method
meth = new CtMethod(CtClass.intType, "getValue", NO_ARGS, clas);
meth.setBody("return m_target." + gmeth.getName() + "();");
clas.addMethod(meth);
// add public setValue method
meth = new CtMethod(CtClass.voidType, "setValue", INT_ARGS, clas);
meth.setBody("m_target." + smeth.getName() + "($1);");
clas.addMethod(meth);
// return binary representation of completed class
return clas.toBytecode();
}
更多精彩
赞助商链接