注释处理器 - 如何获取正在处理的类

时间:2013-08-03 15:56:42

标签: java annotations annotation-processing java-compiler-api

我正在尝试编写一个自定义的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); 
        }
     }
}

3 个答案:

答案 0 :(得分:7)

您无法访问注释处理器正在处理的类,因为尚未编译该类。相反,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
             }
        }
    }
}

答案 1 :(得分:6)

  1. AnnotationProcessing的工作原理。在处理期间,您无法获得Class<?>对象,因为您希望定义的类正在正确编译! 如果您在未知的课程上致电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. 如果您需要更多洞察力,只需在java编译器(JAVA SDK)中包含 tools.jar ,即可获得编译期间使用的更多类型定义。但最有可能的是 - 你不需要来添加这个jar依赖!
  5. 即使ClassNotFoundException 为真,您也会获得roundEnvironment.processingOver()
  6. IN SHORT:在您要使用类类型的所有地方使用TypeMirror
  7. 示例:

    • 从类中获取方法列表:
    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;
    }

答案 2 :(得分:0)

有时您可以使用:subElement.getEnclosingElement() 以便您可以根据需要获取可能是类元素的父元素。

相关问题