web-dev-qa-db-fra.com

Comment obtenir le nom de classe d'annotation, les valeurs d'attribut à l'aide de la réflexion

Je sais que si nous connaissons la classe d'annotation, nous pouvons facilement obtenir l'annotation spécifique et accéder à son attribut. Par exemple:

field.getAnnotation(Class<T> annotationClass) 

Qui renverra une référence d'interface d'annotation spécifique, afin que vous puissiez facilement accéder à ses valeurs.

Ma question est de savoir si je n'ai aucune connaissance préalable de la classe d'annotations particulière. Je veux juste utiliser la réflexion pour obtenir tous les noms de classe d'annotation et leurs attributs au moment de l'exécution dans le but de vider les informations de classe par exemple sous forme de fichier json. Comment puis-je le faire facilement.

Annotation[] field.getAnnotations();

Cette méthode ne renverra que des proxys dynamiques des interfaces d'annotation.

31
Jianwu Chen

Contrairement à ce que l'on pourrait attendre, les éléments d'une annotation ne sont pas des attributs - ce sont en fait des méthodes qui renvoient la valeur fournie ou une valeur par défaut.

Vous devez parcourir les méthodes des annotations et les invoquer pour obtenir les valeurs. Utilisez annotationType() pour obtenir la classe de l'annotation, l'objet renvoyé par getClass() n'est qu'un proxy.

Voici un exemple qui imprime tous les éléments et leurs valeurs de @Resource annotation d'une classe:

@Resource(name = "foo", description = "bar")
public class Test {

    public static void main(String[] args) throws Exception {

        for (Annotation annotation : Test.class.getAnnotations()) {
            Class<? extends Annotation> type = annotation.annotationType();
            System.out.println("Values of " + type.getName());

            for (Method method : type.getDeclaredMethods()) {
                Object value = method.invoke(annotation, (Object[])null);
                System.out.println(" " + method.getName() + ": " + value);
            }
        }

    }
}

Sortie:

Values of javax.annotation.Resource
 name: foo
 type: class Java.lang.Object
 lookup: 
 description: bar
 authenticationType: CONTAINER
 mappedName: 
 shareable: true

Merci à Aaron pour avoir souligné la nécessité de lancer l'argument null pour éviter les avertissements.

67
kapex

Juste pour donner suite à la réponse ci-dessus (je n'ai pas assez de représentants pour y répondre):

method.invoke(annotation, null)

doit être modifié comme suit, sinon il lève une exception:

method.invoke(annotation, (Object[])null) or method.invoke(annotation, new Object[0])
13
Aaron