如何使用 ASM 扫描字段和方法注释?

Max*_*ing 3 java java-bytecode-asm

使用ASM 5.0.4,我试图找到具有特定注释的类的字段和方法。我喜欢避免加载类而不用担心依赖关系。到目前为止,我无法弄清楚如何使用这种方法获取字段/方法注释:

class AnnotationScanner extends ClassVisitor{

    public AnnotationVisitor visitAnnotation(String desc, boolean visible){
        System.out.println("visitAnnotation: desc="+desc+" visible="+visible);
        return super.visitAnnotation(desc,visible);
    }

    public void visitAttribute(Attribute attr){
        System.out.println("visitAttribute: attr="+attr);
        super.visitAttribute(attr);
    }

    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value){
        System.out.println("visitField: access="+access+" name="+name+" desc="+desc+" signature="+signature+" value="+value);
        return super.visitField(access,name,desc,signature,value);
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions){
        System.out.println("visitMethod: access="+access+" name="+name+" desc="+desc+" signature="+signature+" exceptions="+exceptions);
        return super.visitMethod(access,name,desc,signature,exceptions);
    }

    public static void main(String[] args) throws Exception{
        for (String arg : args){
            FileInputStream in = new FileInputStream(new File(arg));
            ClassReader cr = new ClassReader(in);
            cr.accept(new AnnotationScanner(Opcodes.ASM4),0);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

整个示例项目位于GitHub 上

针对一个简单的类运行它

@MyClass(name="annotation scanner")
public class Scannee{
    @MyField(name="a string field") public String aStringField;
    @MyMethod(name="a method")      public void aMethod(){}
}
Run Code Online (Sandbox Code Playgroud)

visitAnnotation: desc=Lorg/springdot/sandbox/asm/MyClass; visible=true
visitField: access=1 name=aStringField desc=Ljava/lang/String; signature=null value=null
visitMethod: access=1 name=<init> desc=()V signature=null exceptions=null
visitMethod: access=1 name=aMethod desc=()V signature=null exceptions=null
Run Code Online (Sandbox Code Playgroud)

但不是字段和方法的注释。

我怎样才能获得字段和方法注释?

dej*_*uth 5

您将需要子类化FieldVisitorMethodVisitor覆盖方法visitAnnotation,类似于您的ClassVisitor子类。例如,

class FieldAnnotationScanner extends FieldVisitor {
    public FieldAnnotationScanner() {
        super(Opcodes.ASM5);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        System.out.println("visitAnnotation: desc="+desc+" visible="+visible);
        return super.visitAnnotation(desc, visible);
    }
}

class MethodAnnotationScanner extends MethodVisitor {
    public MethodAnnotationScanner() {
        super(Opcodes.ASM5);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        System.out.println("visitAnnotation: desc="+desc+" visible="+visible);
        return super.visitAnnotation(desc, visible);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将它们连接到您的AnnotationScannerinvisitFieldvisitMethod. 例如,将您的代码更改为

@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value){
    System.out.println("visitField: access="+access+" name="+name+" desc="+desc+" signature="+signature+" value="+value);
    return new FieldAnnotationScanner();
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions){
    System.out.println("visitMethod: access="+access+" name="+name+" desc="+desc+" signature="+signature+" exceptions="+exceptions);
    return new MethodAnnotationScanner();
}
Run Code Online (Sandbox Code Playgroud)