美文网首页
注解处理器->01文档持续整理

注解处理器->01文档持续整理

作者: 冉桓彬 | 来源:发表于2019-05-31 10:58 被阅读0次

原理就是读入java源代码, 解析注解, 然后生成新的java代码. 新生成的java代码最后被编译成java字节码, 注解助力器不能改变读入的java类, 比如不能加入或删除java方法.

一、AbstractProcessor

@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {...}
    @Override
    public Set<String> getSupportedAnnotationTypes() {...}
    @Override
    public SourceVersion getSupportedSourceVersion() {...}
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {...}
}
1.1 init(...)

所有的注解处理器类都必须有一个无参构造函数. init方法会被注解处理工具调用, 以ProcessingEnvironment作为参数. ProcessingEnvironment作为参数. ProcessingEnvironment提供了一些使用的工具类Elements, Types和Filer.

1.2 getSupportedAnnotationTypes(...)

在这个方法里面你必须指定哪些注解应该被注解处理器注册. 注意, 它的返回值是一个String集合, 包含了你的注解处理器想要处理的注解类型的全称. 换句话说, 你在这里定义你的注解处理器要处理哪些注解.

1.3 process(...)

类似于每个处理器的main()方法. 你可以在这个方法里面编码实现扫描, 处理注解, 生成java文件. 使用RoundEnvironment参数, 你可以查询被特定注解标注的元素.

1.3.1 RoundEnvironment
  • 运行环境, 通过该变量可以获取被特定注解标注的元素的集合
public interface RoundEnvironment {
    Set<? extends Element> getElementsAnnotatedWith(TypeElement a);
    Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a);
}

二、ProcessingEnvironment

public interface ProcessingEnvironment {
    // 用于编译时期在控制台输出日志时使用
    Messager getMessager();
    // 输出文件时使用.
    Filer getFiler();
    // 元素相关的辅助类.
    Elements getElementUtils();
    Types getTypeUtils();
}

三、Elements作为工具类, 提供对应的Element

public interface Elements {
    PackageElement getPackageElement(CharSequence name);
    TypeElement getTypeElement(CharSequence name);
}

四、Element(注意与Elements的区别)

  • 在注解处理器过程中, 我们扫描所有的java源文件, 源代码的每一个部分都是一个特定类型的Element, Element代表程序的元素, 例如包、类或者方法, 每个Element代表一个静态的、语言级别的构件.
package com.example;            // PackageElement
public class Foo {              // TypeElement
    private int a;              // VariableElement
    private Foo other;          // VariableElement
    public Foo () {}            // ExecuteableElement
    public void setA (          // ExecuteableElement
                     int newA   // TypeElement
                     ) {}
}
4.1 Element的子类
类型 概念
ExecutableElement 表示某个类或接口的方法、构造方法
PackageElement 表示一个包程序元素, 提供对有关包及其成员的信息的访问
TypeElement 表示一个类或接口程序元素, 提供对有关类型及其成员的信息的访问
VariableElement 表示一个字段、enum常量、方法或构造方法参数、局部变量或异常参数
4.2 ElementKind
  • 如果要判断一个Element的类型, 最好使用Element.getKind()配合ElementKind一起使用. 例如Class和Interface对应的类型都为TypeElement, 无法进一步细分, 但是通过ElementKind.CLASS、ElementKind.INTERFACE可以将他俩进行细分.
public enum ElementKind {
    // A package: 包类型
    PACKAGE,
    // An enum type: 枚举类型
    ENUM,
    // 类类型或者枚举类型
    CLASS,
    // An annotation type: 注解类型
    ANNOTATION_TYPE,
    // An interface not described by a more specific kind: 接口类型
    INTERFACE,
    // An enum constant: 枚举常量
    ENUM_CONSTANT,
    // A field not described by a more specific kind: 变量
    FIELD,
    // A parameter of a method or constructor: 普通/构造方法的方法参数
    PARAMETER,
    // A local variable: 局部变量
    LOCAL_VARIABLE,
    // A parameter of an exception handler: 
    EXCEPTION_PARAMETER,
    // A method: 方法
    METHOD,
    // constructor: 构造函数
    CONSTRUCTOR,
    // A static initializer: 静态变量初始化
    STATIC_INIT,
    // An instance initializer: 实例初始化
    INSTANCE_INIT,
    // A type parameter: 参数类型
    TYPE_PARAMETER,
    // An implementation-reserved element.  This is not the element you are looking for.
    OTHER,
    // A resource variable. @since 1.7
    RESOURCE_VARIABLE;
}

五、TypeMirror

相关文章

网友评论

      本文标题:注解处理器->01文档持续整理

      本文链接:https://www.haomeiwen.com/subject/rnmetctx.html