Java 如何扫描字段&;使用ASM的方法注释?

Java 如何扫描字段&;使用ASM的方法注释?,java,java-bytecode-asm,Java,Java Bytecode Asm,使用5.0.4,我试图找到具有特定注释的类的字段和方法。我喜欢避免为了不担心依赖性而加载类。 到目前为止,我还不知道如何使用这种方法获得字段/方法注释: class AnnotationScanner extends ClassVisitor{ public AnnotationVisitor visitAnnotation(String desc, boolean visible){ System.out.println("visitAnnotation: desc=

使用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);
        }
    }
}
整个示例项目已启动

在一个简单的类上运行它

@MyClass(name="annotation scanner")
public class Scannee{
    @MyField(name="a string field") public String aStringField;
    @MyMethod(name="a method")      public void aMethod(){}
}
给予

visitanotation:desc=Lorg/springdot/sandbox/asm/MyClass;可见=真
visitField:access=1 name=aStringField desc=Ljava/lang/String;签名=null值=null
visitMethod:access=1 name=desc=()V signature=null异常=null
visitMethod:access=1 name=aMethod desc=()V signature=null异常=null
而不是字段和方法的注释

如何获取字段和方法注释?

您需要子类化并重写方法
VisitAnotation
,类似于
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);
    }
}
然后将它们连接到
visitField
visitMethod
中的
AnnotationScanner
。例如,将代码更改为

@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();
}
不显示如何访问
@MyMethod
注释(
name=“a method”
)的
name
值。要同时读取
a方法
值,您必须再添加两个访问者:

静态类MethodAnnotationScanner扩展MethodVisitor{
MethodAnnotationScanner(){
超级(操作码ASM8);
}
@凌驾
公共注释Visitor visitAnnotation(字符串描述,布尔可见){
System.out.println(“visitMethodAnnotation:type=“+desc”);
返回新的MyAnnotationVisitor();
}
}
静态类方法AnnotationValueScanner扩展AnnotationVisitor{
MethodAnnotationValueScanner(){
超级(操作码ASM8);
}
@凌驾
公共无效访问(字符串名称、对象值){
System.out.println(“VisitMethodNotationValue:+name+”=“+value”);
超级访问(名称、值);
}
}
并通过在
访问方法中重新运行
方法AnnotationScanner
来插入它们:


@凌驾
public方法访问者访问方法(int访问、字符串名称、字符串描述、字符串签名、字符串[]异常){
System.out.println(“visitMethod:access=“+access+”name=“+name+”desc=“+desc+”signature=“+signature+”exceptions=“+exceptions”);
返回新方法AnnotationScanner();
}

您可以在此处看到完整的更新示例:

将解决方案片段合并到。它起作用了。
@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();
}