WEB开发网
开发学院软件开发Java Java 编程的动态性,第 8 部分: 用代码生成取代反... 阅读

Java 编程的动态性,第 8 部分: 用代码生成取代反射

 2010-03-18 00:00:00 来源:WEB开发网   
核心提示: 我不准备详细讨论这些代码,因为如果您一直跟着学习本系列,Java 编程的动态性,第 8 部分: 用代码生成取代反射(5),这里的大多数操作都是所熟悉的(如果您 还没有 看过本系列,请现在阅读 第 5 部分,与使用 Javassist 时一样,我将跳过实现的细节(如果有不熟悉的地方,了解使用 Ja

我不准备详细讨论这些代码,因为如果您一直跟着学习本系列,这里的大多数操作都是所熟悉的(如果您 还没有 看过本系列,请现在阅读 第 5 部分,了解使用 Javassist 的概述)。

用 BCEL 生成

用 BCEL 生成 清单 2 IAccess 的实现类不像使用 Javassist 那样容易,但是也不是很复杂。清单 5 给出了相应的代码。这段代码使用与清单 4 Javassist 代码相同的一组操作,但是运行时间要长一些,因为需要为 BCEL 拼出每一个字节码指令。与使用 Javassist 时一样,我将跳过实现的细节(如果有不熟悉的地方,请参阅 第 7 部分对 BCEL 的概述)。

清单 5. BCEL glue 类构造

/** Parameter types for call with single int value. */ 
  private static final Type[] INT_ARGS = { Type.INT }; 
/** Utility method for adding constructed method to class. */ 
private static void addMethod(MethodGen mgen, ClassGen cgen) { 
  mgen.setMaxStack(); 
  mgen.setMaxLocals(); 
  InstructionList ilist = mgen.getInstructionList(); 
  Method method = mgen.getMethod(); 
  ilist.dispose(); 
  cgen.addMethod(method); 
} 
protected byte[] createAccess(Class tclas, 
  java.lang.reflect.Method gmeth, java.lang.reflect.Method smeth, 
  String cname) { 
   
  // build generators for the new class 
  String tname = tclas.getName(); 
  ClassGen cgen = new ClassGen(cname, "java.lang.Object", 
    cname + ".java", Constants.ACC_PUBLIC, 
    new String[] { "IAccess" }); 
  InstructionFactory ifact = new InstructionFactory(cgen); 
  ConstantPoolGen pgen = cgen.getConstantPool(); 
   
  //. add target object field to class 
  FieldGen fgen = new FieldGen(Constants.ACC_PRIVATE, 
    new ObjectType(tname), "m_target", pgen); 
  cgen.addField(fgen.getField()); 
  int findex = pgen.addFieldref(cname, "m_target", 
    Utility.getSignature(tname)); 
   
  // create instruction list for default constructor 
  InstructionList ilist = new InstructionList(); 
  ilist.append(InstructionConstants.ALOAD_0); 
  ilist.append(ifact.createInvoke("java.lang.Object", "<init>", 
    Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); 
  ilist.append(InstructionFactory.createReturn(Type.VOID)); 
  // add public default constructor method to class 
  MethodGen mgen = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, 
    Type.NO_ARGS, null, "<init>", cname, ilist, pgen); 
  addMethod(mgen, cgen); 
   
  // create instruction list for setTarget method 
  ilist = new InstructionList(); 
  ilist.append(InstructionConstants.ALOAD_0); 
  ilist.append(InstructionConstants.ALOAD_1); 
  ilist.append(new CHECKCAST(pgen.addClass(tname))); 
  ilist.append(new PUTFIELD(findex)); 
  ilist.append(InstructionConstants.RETURN); 
   
  // add public setTarget method 
  mgen = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, 
    new Type[] { Type.OBJECT }, null, "setTarget", cname, 
    ilist, pgen); 
  addMethod(mgen, cgen); 
   
  // create instruction list for getValue method 
  ilist = new InstructionList(); 
  ilist.append(InstructionConstants.ALOAD_0); 
  ilist.append(new GETFIELD(findex)); 
  ilist.append(ifact.createInvoke(tname, gmeth.getName(), 
    Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 
  ilist.append(InstructionConstants.IRETURN); 
   
  // add public getValue method 
  mgen = new MethodGen(Constants.ACC_PUBLIC, Type.INT, 
    Type.NO_ARGS, null, "getValue", cname, ilist, pgen); 
  addMethod(mgen, cgen); 
   
  // create instruction list for setValue method 
  ilist = new InstructionList(); 
  ilist.append(InstructionConstants.ALOAD_0); 
  ilist.append(new GETFIELD(findex)); 
  ilist.append(InstructionConstants.ILOAD_1); 
  ilist.append(ifact.createInvoke(tname, smeth.getName(), 
    Type.VOID, INT_ARGS, Constants.INVOKEVIRTUAL)); 
  ilist.append(InstructionConstants.RETURN); 
   
  // add public setValue method 
  mgen = new MethodGen(Constants.ACC_PUBLIC, Type.VOID, 
    INT_ARGS, null, "setValue", cname, ilist, pgen); 
  addMethod(mgen, cgen); 
   
  // return bytecode of completed class 
  return cgen.getJavaClass().getBytes(); 
} 

上一页  1 2 3 4 5 6 7 8  下一页

Tags:Java 编程 动态性

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接