@Override 仅对 Java编译器 有用,为Java编译器 引用一条新的编译规则 ,编译完成后,它的使命也结束了 @Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
// 元注解@Target:用来限定目标注解所能标注的Java结构
// 元注解@Retention:用来限定目标注解的生命周期
//      SOURCE:源代码,一旦源代码被编译为字节码,注解便会被擦除
//      CLASS:源代码+字节码
//      RUNTIME:源代码+字节码+运行时
 
    
 
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface CheckGetter {
}
 
  CheckGetter的目的:遍历被标注的类中的实例字段,并检查有没有对应的getter方法
public interface Processor {
    void init(ProcessingEnvironment processingEnv);
    Set<String> getSupportedAnnotationTypes();
    SourceVersion getSupportedSourceVersion();
    boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
    ...
}
 
  init 方法中  AbstractProcessor 实现了 init , getSupportedAnnotationTypes 和 getSupportedSourceVersion 方法 
 它的子类可以通过 @SupportedAnnotationTypes 和 @SupportedSourceVersion 注解来声明所支持的 注解类型 以及 Java版本 
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedAnnotationTypes("CheckGetter")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class CheckGetterProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // annotations:该注解处理器所能处理的注解类型
        // roundEnv:囊括当前轮生成的抽象语法树RoundEnvironment
        // roundEnv.getElementsAnnotatedWith(CheckGetter.class) -> 获取所有被@CheckGetter注解的类
        for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(CheckGetter.class))) {
            for (VariableElement field : ElementFilter.fieldsIn(annotatedClass.getEnclosedElements())) {
                if (!containsGetter(annotatedClass, field.getSimpleName().toString())) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                            String.format("getter not fund for '%s.%s'.", annotatedClass.getSimpleName(),
                                    field.getSimpleName()));
                }
            }
        }
        return false;
    }
    private static boolean containsGetter(TypeElement typeElement, String name) {
        // 拼接getter名称
        String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
        for (ExecutableElement executableElement : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
            if (!executableElement.getModifiers().contains(Modifier.STATIC)
                    && executableElement.getSimpleName().toString().equals(getter)
                    && executableElement.getParameters().isEmpty()) {
                return true;
            }
        }
        return false;
    }
}
 
  process方法涉及处理各种不同类型的Element,分别指代Java程序的各个 结构
// package me.zhongmingmao.advanced.annotation; // PackageElement
@CheckGetter
public class Foo { // TypeElement
    int a; // VariableElement
    static int b; // VariableElement
    Foo() { // ExecutableElement
    }
    void setA( // ExecutableElement
               int newA // VariableElement
    ) {
    }
}
 
   Java结构之间也存在从属关系, TypeElement.getEnclosedElements() 将获取 字段,构造器和方法 
在将注解处理器编译成class文件后,就可以将其 注册为Java编译器的插件 ,并用来 处理其他源代码
$ ll total 24 -rw-r--r-- 1 zhongmingmao staff 147B 1 7 22:53 CheckGetter.java -rw-r--r-- 1 zhongmingmao staff 2.0K 1 7 22:54 CheckGetterProcessor.java -rw-r--r-- 1 zhongmingmao staff 316B 1 7 22:55 Foo.java $ javac CheckGetter.java CheckGetterProcessor.java $ javac -cp . -processor CheckGetterProcessor Foo.java 错误: getter not fund for 'Foo.a'. 错误: getter not fund for 'Foo.b'. 2 个错误 $ ll total 40 -rw-r--r-- 1 zhongmingmao staff 385B 1 7 22:57 CheckGetter.class -rw-r--r-- 1 zhongmingmao staff 147B 1 7 22:53 CheckGetter.java -rw-r--r-- 1 zhongmingmao staff 3.1K 1 7 22:57 CheckGetterProcessor.class -rw-r--r-- 1 zhongmingmao staff 2.0K 1 7 22:54 CheckGetterProcessor.java -rw-r--r-- 1 zhongmingmao staff 316B 1 7 22:55 Foo.java
  
 
转载请注明出处:http://zhongmingmao.me/2019/01/07/jvm-advanced-annotation-processor/
访问原文「 JVM进阶 -- 浅谈注解处理器 」获取最佳阅读体验并参与讨论