2016-12-08 1 views
2

Actuellement, j'écris un processeur d'annotation, qui va générer du nouveau code source. Ce processeur est isolé de l'application elle-même, car c'est une étape dans la construction du projet et j'ai séparé l'ensemble du système de construction de l'application.Traitement d'annotation inconnu Annotation

C'est là que le problème commence, car je veux traiter une annotation créée dans l'application. Appelons-le CustomAnnotation. avec le nom complet com.company.api.annotation.CustomAnnotation.

Dans le processeur, je peux rechercher des annotations par le nom complet, ce qui est vraiment bien. Maintenant, je crois être en mesure d'obtenir les méthodes, champ, etc qui sont annotées depuis que je peux appeler la fonction getElementsAnnotatedWith avec TypeElement au lieu de classe.

Maintenant, notre CustomAnnotation a des champs et variables et normalement je recevrais l'annotation se présente comme suit: Class annotation = Element.getAnnotation(Class) Mais je ne peux pas utiliser ce depuis CustomAnnotation est pas disponible comme classe Object (bien sûr, on ne sait pas au processeur. J'ai essayé d'utiliser TypeMirror et d'autres choses disponibles mais rien ne semble fonctionner.

Est-ce que quelqu'un sait comment obtenir l'Annotation pour lire ses valeurs?

EDIT: Regardons cette implémentation:

@SupportedAnnotationTypes("com.company.api.annotation.CustomAnnotation") 
@SupportedSourceVersion(SourceVersion.RELEASE_8) 
public class CustomProcessor extends AbstractProcessor 
{ 

    public CustomProcessor() 
    { 
    super(); 
    } 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) 
    { 
    TypeElement test = annotations.iterator().next(); 

    for (Element elem : roundEnv.getElementsAnnotatedWith(test)) 
    { 
     //Here is where I would get the Annotation element itself to 
     //read the content of it if I can use the Annotation as Class Object. 
     SupportedAnnotationTypes generated = elem.getAnnotation(SupportedAnnotationTypes.class); 
    } 
} 

Cependant je n'ai pas utiliser CustomAnnotation.class car il n'existe pas dans cet environnement. Comment puis-je faire cela sans posséder l'objet Class?

+0

Je ne sais pas ce que vous demandez ... ne pouvez-vous faire Class.forName () premier? – GhostCat

+2

Qu'est-ce qui ne va pas avec ['Element.getAnnotationMirrors()'] (https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html#getAnnotationMirrors--), suivi de par ['AnnotationMirror.getElementValues ​​()'] (https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationMirror.html#getElementValues--)? – Holger

+0

Merci @Holger c'est exactement ce dont j'avais besoin !! Je n'ai pas trouvé de question avec ce problème et je ne savais pas que getAnnotationMirrors serait ce dont j'avais besoin. – Nico

Répondre

2

Vous pouvez interroger les annotations comme AnnotationMirror qui ne nécessite pas le type d'annotation pour une exécution chargée Class:

@Override 
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
    for(TypeElement test: annotations) { 
     for(Element elem : roundEnv.getElementsAnnotatedWith(test)) { 
      System.out.println(elem); 
      for(AnnotationMirror am: elem.getAnnotationMirrors()) { 
       if(am.getAnnotationType().asElement()==test) 
        am.getElementValues().forEach((ee,av) -> 
         System.out.println("\t"+ee.getSimpleName()+" = "+av.getValue()) 
        ); 
      } 
     } 
    } 
    return true; 
} 
+0

Bonjour Holger, j'ai juste une petite question. J'ai donc utilisé votre commentaire et j'ai cette carte de la paix? extends ExecutableElement,? extends AnnotationValue> annotationValues ​​= annotationMirrors.get (0) .getElementValues ​​(); 'et cette carte ressemble à ceci:' Key: query(), Value: "du rôle r où r.deleted = false et r.name =: nom "' mais quand je veux obtenir la valeur comme ceci: 'AnnotationValue annotationValue = annotationValues.get (" query ");' ou même en utilisant query() dans le get, tout ce que je reçois est 'null'. Savez-vous comment je peux obtenir la valeur sans ces boucles? – Nico

+1

La carte a 'ExecutableElement' comme clé, donc les recherches avec' String' ne peuvent pas fonctionner. Puisque votre méthode 'process' reçoit le type d'annotation lui-même en tant que' TypeElement', vous pouvez utiliser 'getEnclosedElements()' pour obtenir les membres d'annotation déclarés. Vous pouvez utiliser leurs noms pour vérifier quel 'Element' est la clé dont vous avez besoin. Une fois que vous l'avez, vous pouvez l'utiliser à plusieurs reprises pour rechercher la valeur de chaque élément annoté. – Holger