2013-08-03 153 views
5

我正在嘗試編寫一個自定義的處理器。 註解處理器將在編譯時處理每個類文件以檢查註釋, 但是,我如何才能獲取它當前正在處理的類? 我只能在下面的代碼中獲得類名。註釋處理器 - 如何獲得它正在處理的類

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

您無法訪問Annotation Processor正在處理的Class,因爲Class尚未編譯。相反,Java提供了類似的Elements 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

你說「...有更多關於正在編譯的類的信息,而不僅僅是它的名字」,但是你怎麼得到類名呢? – Matthias

+0

類名稱將位於Element.getSimpleName()中http://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Element.html#getSimpleName%28%29 –

3
  1. This is not AnnotationProcessing是如何工作的。在處理過程中無法獲得Class<?>對象,因爲想要定義的類正在編譯爲NOW! 如果您致電getClass()上未知類別或使用Class<?> clazz = Class.forName("com.your.fancy.Class")你會得到java.lang.ClassNotFoundException這是完全沒問題的。
  2. 您需要使用類如javax.lang.model.element.Elementjavax.lang.model.element.ExecutableElement來描述/讀取您的類定義。
  3. javax.lang.model.*javax.lang.model.type.TypeMirror來形容類,它們的屬性,方法等
  4. 如果您需要更深入的瞭解,只包括的tools.jar從Java編譯器(JAVA SDK),以獲得更多的類型定義它們是在編譯期間使用。但最有可能 - 你不需要添加這個jar依賴!
  5. 即使在roundEnvironment.processingOver()true之後,您將獲得ClassNotFoundException
  6. IN SHORT:在您想要使用類型的所有地方使用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; }
  • get方法名稱:

    • 從一個類的方法獲取列表
    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