5

Я пытаюсь написать собственный обработчик Anntoation. Обработчик аннотации обрабатывает каждый файл класса во время компиляции для проверки аннотаций, Но как я могу получить класс, который он сейчас обрабатывает? Я могу получить имя класса только в следующих кодах.Обработчик аннотации - Как получить класс, который обрабатывает

public class AnnotationProcessor extends AbstractProcessor { 
    ...... 
    @Override 
    public boolean process(Set<? extends TypeElement> annotations, 
     RoundEnvironment roundEnv) { 

    Set<? extends Element> rootE=roundEnv.getRootElements(); 
     for(Element e: rootE) { 
     if(e.getKind()==ElementKind.CLASS) { 
      String className= e.getSimpleName().toString(); 
      processingEnv.getMessager().printMessage(javax.tools.Diagnostic.Kind.WARNING,className, e); 
     } 
    } 
} 

ответ

7

Вы не можете получить доступ к классу, обработанному обработкой аннотации, поскольку класс еще не скомпилирован. Вместо этого Java предлагает аналогичные элементы api для проверки стиля входного сигнала.

Элемент (который вы нашли с помощью roundEnv.getRootElements()) имеет гораздо больше информации о компилируемом классе, чем только его имя. Тонна полезной информации можно найти, используя ElementVisitors:

http://docs.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html http://docs.oracle.com/javase/6/docs/api/javax/lang/model/util/ElementKindVisitor6.html

В том числе конструктор классов, методов, полей и т.д.

Вот как его использовать:

public class AnnotationProcessor extends AbstractProcessor { 
...... 
    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 

     Set<? extends Element> rootE=roundEnv.getRootElements(); 
     for(Element e: rootE) { 
      for(Element subElement : e.getEnclosedElements()){ 
       subElement.accept(new ExampleVisitor(), null); // implement ExampleVisitor 
      } 
     } 
    } 
} 
+0

Выражаем вам за помощь: D – user1004413

+0

Вы говорите: «... имеет гораздо больше информации о компилируемом классе, чем просто его имя», но как _do_ вы получаете имя класса? – Matthias

+0

Имя класса будет в Element.getSimpleName() http://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Element.html#getSimpleName%28%29 –

3
  1. Этот НЕ как работает AnnotationProcessing. Вы не можете получить объект Class<?> во время обработки, потому что классы, которые вы хотите определить , скомпилированы прямо сейчас.! Если вы звоните getClass() в неизвестном классе или используете Class<?> clazz = Class.forName("com.your.fancy.Class"), вы получите java.lang.ClassNotFoundException, что совершенно нормально.
  2. Для описания/чтения определений классов вам необходимо использовать классы, такие как javax.lang.model.element.Element и javax.lang.model.element.ExecutableElement.
  3. javax.lang.model.* имеет javax.lang.model.type.TypeMirror для описания классов, их поля, методы и т.д.
  4. Если вам нужно больше понимания, просто включают tools.jar из Java компилятор (Java SDK), чтобы получить больше определений типа, которые используется во время компиляции. Но, скорее всего, вы - НЕ ДОЛЖНЫ, чтобы добавить эту зависимость jar!
  5. Вы получите ClassNotFoundException даже после roundEnvironment.processingOver() is true.
  6. В КРАТКЕ: ИСПОЛЬЗОВАНИЕ TypeMirror во всех местах, где вы хотели использовать тип класса.

Примеры:

  • получить список методов из класса:
имени метода
public static @Nonnull List getMethods(@Nonnull Element annotationElem, @Nonnull RoundEnvironment roundEnvironment) { 
    List outList = new ArrayList(); 

    String simpleName = annotationElem.getSimpleName().toString(); 
    for (Element elem : roundEnvironment.getRootElements()) 
     if (elem.getSimpleName().toString().equals(simpleName)) 
      for (Element methodDeclaration :elem.getEnclosedElements()) 
       if (methodDeclaration instanceof ExecutableElement) 
        outList.add((ExecutableElement)methodDeclaration); 

    return outList; 
}
  • получить от объявления методы:
public static TypeMirror getMethodFirstParam(@Nonnull ExecutableElement method, int n) { 
    List parameters = ((ExecutableElement) method).getParameters(); 
    if (parameters != null && parameters.size() > 0) 
     return parameters.get(n).asType(); 
    return null; 
}
+0

Is annotationElem - корневой элемент roundEnvironment? – Sunnyday