jeudi 24 mars 2022

Get the value of an annotation with reflection (without knowing the concrete annotation type)

I have the following class:

public final class SomeClass {
    
    @Signature("some info")
    public void someMethod() {

    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD })
    @Inherited
    private @interface Signature {

        String value();
    }    
}

This class is not in my source code nor in a dependency, it's compiled from a resource file on-the-fly at runtime. That means, the symbol Signature.class (as well as SomeClass.class) do not exist in my class loader and will never do at compile time, so I can't do the easy:

Signature signature = method.getAnnotation(Signature.class);
signature.value();

I would like to retrieve the value that is assigned to the annotation @Signature at runtime, but I'm being unable to. All I know is that the method will only have one annotation (the @Signature annotation) and that this annotation will always have one parameter value, but that's all I know.

This is my (raw) attempt:

Class<?> compiledClass = compiler.compile(classSourceCode); //this properly return the class instance
for (Method method : compiledClass.getDeclaredMethods()) {
    for (Annotation annotation : method.getAnnotations()) {
        Class<? extends Annotation> realType = annotation.annotationType();
        for (Method annotationMethod : realType.getDeclaredMethods()) {
            System.out.println(annotationMethod.invoke(annotation)); //<-- THIS FAILS
        }
    }
}     

The failure that I get at runtime is:

java.lang.IllegalAccessException: class SomeClass cannot access a member of interface SomeClass$Signature with modifiers "public abstract"

The method that I get is the method value().

How can I do that?





Aucun commentaire:

Enregistrer un commentaire