2011-03-24 36 views
2

我使用了ASM框架的ClassAdapter寫字節碼轉換。如果類中存在自定義註釋,我想添加一些方法並使類實現一個接口。添加方法工作正常,但我想知道什麼是最好的方法是讓類實現一個接口。由於visitAnnotation僅在visit之後被調用,所以我需要以某種方式延遲調用超級訪問方法並緩衝所有需要的信息。添加接口的轉換類,如果註釋存在

有沒有人實現過類似的東西?我是否應該使用asm的樹api來實現這一點,儘管包文檔建議儘可能避免它?

這裏是改造的總體結構:

public class MyClassAdapter extends ClassAdapter { 
    private String classname; 
    private boolean instrument; 

    public PropertyChangeSupportAdapter(ClassVisitor cv) { 
     super(cv); 
    } 

    @Override 
    public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { 
     super.visit(version, access, name, signature, superName, interfaces); 
     this.classname = name; 
    } 

    @Override 
    public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { 
     if (desc.equals("Lmypackage/MyAnnotation;")) { 
      instrument = true; 
      System.out.println("Instrumenting " + classname); 
     } 
     return super.visitAnnotation(desc, visible); 
    } 

    @Override 
    public void visitEnd() { 
     if (instrument) { 
      // add methods 
     } 
    } 
} 

回答

2

我結束了使用ClassNode和ClassAdapter API的組合。第一類文件解析成ClassNode:

ClassReader cr = new ClassReader(inputStream); 
ClassNode cn = new ClassNode(); 
cr.accept(cn, 0); 

然後,它可以檢查wheter cn.visibleAnnotation或cn.invisibleAnnotations包含我的註釋,也如果類已經實現了我想補充的接口。在這種情況下,第二步可以跳過。該ClassNode然後可以使用ClassAdapter API中的問題轉化:

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 
CheckClassAdapter ca = new CheckClassAdapter(cw); 
ClassVisitor cv = new PropertyChangeSupportAdapter(ca); 
cn.accept(cv); 

package documentation,這是我的問題的原因的說明,提到這些API之間有很大的性能差異:

使用ClassAdapter比使用ClassNode讀取,修改和編寫類要快兩倍。 ...這也是爲什麼當可能的時候建議不要使用這個類適配器的原因。

再次重讀之後,差異似乎來自於使用ClassNode來操縱字節碼。但是,我沒有基準測試這種混合解決方案。