【问题标题】:how to scan field&method annotations with ASM?如何使用 ASM 扫描字段和方法注释?
【发布时间】:2015-12-24 19:08:45
【问题描述】:

使用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);
        }
    }
}

整个示例项目位于GitHub

针对一个简单的类运行它

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

给予

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

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

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

【问题讨论】:

    标签: java java-bytecode-asm


    【解决方案1】:

    The example 没有显示如何访问 @MyMethod 注释 (name="a method") 的 name 值。要同时读取 a method 值,您必须再添加两个 Visitor

    static class MethodAnnotationScanner extends MethodVisitor {
            MethodAnnotationScanner() { 
              super(Opcodes.ASM8); 
        }
    
        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            System.out.println("visitMethodAnnotation: type= " + desc);
            return new MyAnnotationVisitor();
        }
    }
    
    static class MethodAnnotationValueScanner extends AnnotationVisitor {
        MethodAnnotationValueScanner() { 
            super(Opcodes.ASM8); 
        }
    
        @Override
        public void visit(String name, Object value) {
            System.out.println("visitMethodAnnotationValue: " + name + " = " + value);
            super.visit(name, value);
        }
    }
    

    并通过将MethodAnnotationScanner 重新插入visitMethod 来插入它们:

    
    @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();
    }
    

    您可以在此处查看完整更新的示例:how-to-read-a-java-class-method-annotation-value-with-asm

    【讨论】:

      【解决方案2】:

      您需要继承 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);
          }
      }
      

      然后在visitFieldvisitMethod 中将它们连接到您的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();
      }
      

      【讨论】:

      • 将解决方案 sn-ps 纳入sample code。它有效。
      猜你喜欢
      • 2012-10-19
      • 1970-01-01
      • 2015-02-17
      • 2015-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 1970-01-01
      相关资源
      最近更新 更多