问题
How can I read read the value of a Java method annotation at runtime with ASM ?
The Annotation has only a CLASS
RetentionPolicy
, so it's not possible to do that with Reflections.
| Policy CLASS
: Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time
Example:
I want to extract the value Carly Rae Jepsen
out of the artist
field at runtime:
public class SampleClass {
@MyAnnotation(artist = "Carly Rae Jepsen")
public void callMeMaybe(){}
}
@Documented
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String artist() default "";
}
But why?
Can't you just change the RetentionPolicy
to RUNTIME
and do it with reflections?
In short: No. I use the modelmapper framework (Simple, Intelligent, Object Mapping). There I specify bidirectional mappings between Java classes by annotated methods. I wan't to reuse this information of hierarchical mappings, for change event propagation. But the provided mapstruct org.mapstruct.Mapping
Annotation has CLASS RetentionPolicy
. This is why I need to read that information out of the class files - and need ASM.
回答1:
There are many samples which show the setup with asm and reading annotaions. But they don't showed it, for method annotations and how to also read the annotation value.
Minimal example how to do it:
import org.objectweb.asm.*;
public class AnnotationScanner extends ClassVisitor {
public static void main(String[] args) throws Exception {
ClassReader cr = new ClassReader(SampleClass.class.getCanonicalName());
cr.accept(new AnnotationScanner(), 0);
}
public AnnotationScanner() {
super(Opcodes.ASM8);
}
static class MyAnnotationVisitor extends AnnotationVisitor {
MyAnnotationVisitor() {
super(Opcodes.ASM8);
}
@Override
public void visit(String name, Object value) {
System.out.println("annotation: " + name + " = " + value);
super.visit(name, value);
}
}
static class MyMethodVisitor extends MethodVisitor {
MyMethodVisitor() {
super(Opcodes.ASM8);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
System.out.println("annotation type: " + desc);
return new MyAnnotationVisitor();
}
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
System.out.println("method: name = " + name);
return new MyMethodVisitor();
}
}
Maven dependecy
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>8.0.1</version>
</dependency>
▶ It will print:
method: name = callMeMaybe
annotation type: Lorg/springdot/sandbox/asm/simple/asm/MyAnnotation;
annotation: artist = Carly Rae Jepsen
来源:https://stackoverflow.com/questions/61807758/how-to-read-a-java-class-method-annotation-value-with-asm