Java javax.annotation.processing.Processor (注解处理器)

概念

注解处理器(Annotation Processor)是javac内置的一个用于编译时扫描和处理注解(Annotation)的工具。简单的说,在源代码编译阶段,通过注解处理器,我们可以获取源文件内注解(Annotation)相关内容javax.annotation.processing.Processor用于替换JDK6之前的APT(Annotatino Processing Tool)

用途

由于注解处理器可以在程序编译阶段工作,所以我们可以在编译期间通过注解处理器进行我们需要的操作。比较常用的用法就是在编译期间获取相关注解数据,然后动态生成.java源文件(让机器帮我们写代码),通常是自动产生一些有规律性的重复代码,解决了手工编写重复代码的问题,大大提升编码效率。

技术

javax.annotation.processing.Processor

public interface Processor {
   //返回此 processor 识别的选项。处理工具的实现必须提供一种方式来传递特定于 processor 的选项,这些选项不同于传递给工具自身的选项,
    Set<String> getSupportedOptions();
//返回此 processor 支持的注释类型的名称。结果元素可能是某一受支持注释类型的规范(完全限定)名称。它也可能是 "name.*" 形式的名称,表示所有以 "name." 开头的规范名称的注释类型集合。最后,"*" 自身表示所有注释类型的集合,包括空集。注意,processor 不应声明 "*",除非它实际处理了所有文件;声明不必要的注释可能导致在某些环境中的性能下降。
    Set<String> getSupportedAnnotationTypes();

//用于指定你的java版本,一般返回:SourceVersion.latestSupported()
    SourceVersion getSupportedSourceVersion();

//用处理环境初始化处理器。
    void init(ProcessingEnvironment processingEnv);

   //处理先前 round 产生的类型元素上的注释类型集,并返回这些注释是否由此 processor 声明。如果返回 true,则这些注释已声明并且不要求后续 processor 处理它们;如果返回 false,则这些注释未声明并且可能要求后续 processor 处理它们。processor 可能总是返回相同的 boolean 值,或者可能基于所选择的标准而返回不同的结果。
如果 processor 支持 "*" 并且根元素没有注释,则输入集合将为空。processor 必须妥善处理空注释集。

    boolean process(Set<? extends TypeElement> annotations,
                    RoundEnvironment roundEnv);
quot;),
     
    Iterable<? extends Completion> getCompletions(Element element,
                                                  AnnotationMirror annotation,
                                                  ExecutableElement member,
                                                  String userText);
}

javax.annotation.processing.AbstractProcessor

对其父类的获取配置信息的扩充,使其获取支持的版本号,扫描的注解信息等可以使用注解方式等,推荐使用

javax.annotation.processing.SupportedSourceVersion 直接支持的版本
javax.annotation.processing.SupportedOptions 支持的选项参数名称。通过getOptions方法获取选项参数值
javax.annotation.processing.SupportedAnnotationTypes 支持的注解 
 public Set<String> getSupportedOptions() {
        SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class);
        if  (so == null)
            return Collections.emptySet();
        else
            return arrayToSet(so.value());
    }

  public Set<String> getSupportedAnnotationTypes() {
            SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
            if  (sat == null) {
                if (isInitialized())
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                             "No SupportedAnnotationTypes annotation " +
                                                             "found on " + this.getClass().getName() +
                                                             ", returning an empty set.");
                return Collections.emptySet();
            }
            else
                return arrayToSet(sat.value());
        }
 public SourceVersion getSupportedSourceVersion() {
        SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class);
        SourceVersion sv = null;
        if (ssv == null) {
            sv = SourceVersion.RELEASE_6;
            if (isInitialized())
                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                         "No SupportedSourceVersion annotation " +
                                                         "found on " + this.getClass().getName() +
                                                         ", returning " + sv + ".");
        } else
            sv = ssv.value();
        return sv;
    }

Demo

  • @SupportedAnnotationTypes(“org.mapstruct.Mapper”) 只支持org.mapstruct.Mapper注解
  • @SupportedAnnotationTypes(“javax.xml.bind.annotation.*”) 支持javax.xml.bind.annotation 包下所有注解
  • @SupportedAnnotationTypes("*") 支持所有注解

版权声明:本文为jinlong59421原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。