13

I am trying to write a custom Anntoation processor. The annotation processor will process each class file at compile time to check annotations, But how am i able to get the class that it is currently processing? I am only able to get the class name in the following codes.

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); 
        }
     }
}
4

3 回答 3

14

您无法访问注释处理器正在处理的类,因为该类尚未编译。相反,Java 提供了类似的 Elements api,用于对输入源进行反射式检查。

元素(您通过使用 找到roundEnv.getRootElements())包含更多关于正在编译的类的信息,而不仅仅是其名称。使用 ElementVisitor 可以找到大量有用的信息:

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
             }
        }
    }
}
于 2013-08-13T17:04:47.203 回答
12
  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. 如果您需要更多洞察力,只需包含java 编译器 (JAVA SDK) 中的tools.jar即可获得更多在编译期间使用的类型定义。但最有可能 - 你不需要添加这个 jar 依赖项!
  5. 你会得到ClassNotFoundException即使roundEnvironment.processingOver()真的
  6. 简而言之:在您想使用 Class 类型的所有地方使用 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;
}
于 2017-02-28T13:57:30.923 回答
0

有时您可以使用:subElement.getEnclosingElement()这样您就可以获得可能是您想要的类元素的父元素。

于 2021-04-25T10:41:34.313 回答