android日常开发

Annotation Processor 相关知识点

2019-06-24  本文已影响0人  众少成多积小致巨

1.java注解包(javax.annotation.processing)

用于声明注释处理器和允许注释处理器与注释处理工具环境通信的设施。


1.1、Processor


注释处理器接口

注释处理按rounds的顺序进行。在每一轮中,可能会要求处理器process在上一轮产生的源文件和类文件上发现的注释的一个子集。第一轮处理的输入是工具运行的初始输入;这些初始输入可以被认为是虚拟第五轮处理的输出。如果一个处理器被要求在给定的一轮进行处理,那么将被要求处理后续的回合,包括最后一轮,即使没有注释来处理它。工具基础设施还可能要求处理器处理由工具操作隐含生成的文件。

Processor每个实现Processor必须提供一个公共的无参数构造函数,供工具用来实例化处理器。工具基础设施将与实现此接口的类进行交互,如下所示:

如果没有使用现有的Processor对象,要创建一个处理器的实例,该工具将调用处理器类的无参数构造函数。

接下来,该工具使用适当的ProcessingEnvironment调用init方法。

此后,工具调用getSupportedAnnotationTypesgetSupportedOptions,并getSupportedSourceVersion。这些方法只能在每次运行时调用一次,而不是每轮调用。

适当时,该工具在Processor对象上调用process方法;不会为每一轮创建一个新的Processor对象。


1.1.1 方法

Set<String> getSupportedAnnotationTypes​()

返回此处理器支持的注释类型的名称。结果的元素可能是支持的注释类型的规范(完全限定)名称。或者它可能是形式“的name.*”代表了集中的所有注释类型的规范名称以“开头的name.”。在任何一种情况下,注释类型的名称可以前面加上一个模块名称,后跟一个"/"字符


void init​(ProcessingEnvironment processingEnv)

使用处理环境初始化处理器。             

processingEnv- 工具框架为处理器提供的设施的环境


boolean process​(SetTypeElement> annotations,RoundEnvironmentroundEnv)

对来自前一轮的类型元素处理一组注释类型,并返回此处理器是否声明这些注释类型。如果返回true,则会声明注释类型,并且不会要求后续处理器处理它们;如果返回false,则注释类型是无人认领的,并且后处理器可能被要求处理它们。处理器可以总是返回相同的布尔值,或者可以根据其自己选择的标准来改变结果。

如果处理器支持"*"且根元素没有注释,输入集将为空。AProcessor必须优雅地处理一组空的注释。

annotations- 请求处理的注释类型

roundEnv- 有关当前和前一轮的信息的环境

结果:该处理器是否声明该组注释类型 

1.1.2 AbstractProcessor

一个抽象的注释处理器,被设计为大多数具体注解处理器的一个方便的超类。此类检查注释值来计算options,annotation types,并source version其亚型支持。子类可以覆盖该类中任何方法的实现和规范,只要符合该方法的一般Processor合同即可。


1.2、ProcessingEnvironment

处理器可以使用框架提供的工具来编写新文件,报告错误消息和查找其他实用程序。

方法

Filer getFiler​()

返回用于创建新的源,类或辅助文件的文件管理器。

结果 文件管理员

Elements getElementUtils​()

返回一些用于操作元素的实用方法的实现

结果 元素实用程序


1.3、RoundEnvironment

方法


Set<? extends Element> getRootElements​()

返回上一轮生成的注释处理的root elements 。

结果 上一轮生成的注释处理的根元素,如果没有,则为空集

Set<? extends Element> getElementsAnnotatedWith​(TypeElement a)

返回使用给定注释类型注释的元素。 注释可以直接显示或继承。 仅返回本轮注释处理中包含的包元素,模块元素和类型元素,或者返回在其中声明的成员,构造函数,参数或类型参数的声明。 包含的类型元素为root types ,嵌套在其中的任何成员类型。 包的元素不包括在内,因为该包的package-info文件已创建。 同样,模块的元素也不被认为是因为该模块的一个module-info文件被创建

参数 a - 请求的注释类型 

结果 用给定注释类型注释的元素,如果没有,则为空集 异常 IllegalArgumentException - 如果参数不表示注释类型

Set<? extends Element> getElementsAnnotatedWith​(Class<? extends Annotation> a)

返回使用给定注释类型注释的元素。 注释可以直接显示或继承。 仅返回本轮注释处理中包含的包元素,模块元素和类型元素,或者返回在其中声明的成员,构造函数,参数或类型参数的声明。 包含的类型元素为root types ,嵌套在其中的任何成员类型。 软件包中的元素不被认为包括在内,因为该软件包的package-info文件已创建。 同样,模块的元素也不被认为是因为该模块的一个module-info文件被创建

参数 a - 请求的注释类型 

结果 用给定注释类型注释的元素,如果没有,则为空集 异常 IllegalArgumentException - 如果参数不表示注释类型


1.4、Filer

该接口支持通过注释处理器创建新文件。以这种方式创建的文件将通过实现此界面的注释处理工具知道,更好地使工具能够管理它们。三种文件:源文件,类文件和辅助资源文件。 文件创建方法采用可变数量的参数,以允许将源元素作为工具基础设施的提示来提供更好的管理依赖关系。 发起元素是引起注释处理器尝试创建新文件的类型或包(代表package-info文件)或模块(代表module-info文件)。

在每次运行注释处理工具期间,只能创建一个具有给定路径名的文件。 如果该文件在首次尝试创建之前已经存在,则旧的内容将被删除。 任何后续尝试在运行期间创建相同的文件将会抛出一个FilerException ,同时也将尝试为相同类型的名称或相同的包名称创建类文件和源文件。 该工具的initial inputs被认为是由第零轮创造的; 因此,尝试创建与其中一个输入对应的源文件或类文件将导致一个FilerException 。

一般来说,处理器不得有意试图覆盖某些处理器未生成的现有文件。 A Filer可能会拒绝尝试打开与现有类型相对应的文件,如java.lang.Object 。 同样,注释处理工具的调用者也不得故意地配置工具,使得发现的处理器将尝试覆盖未生成的现有文件。

如果环境配置为使得该类型可访问,则处理器可以指示通过包括javax.annotation.Generated注释来生成源文件或类文件。

方法

JavaFileObject createSourceFile​(CharSequence name, Element... originatingElements) throws IOException

创建一个新的源文件并返回一个对象以允许写入它。 可以创建类型的源文件或包。 文件的名称和路径(相对于root output location for source files )基于要在该文件中声明的项目的名称以及项目的指定模块(如果有)。 如果在单个文件(即单个编译单元)中声明了多个类型,则该文件的名称应对应于主体顶级类型的名称(例如公共的)。

JavaFileObjectcreateClassFile​(CharSequencename,Element... originatingElements) throwsIOException

创建一个新的类文件,并返回一个对象以允许写入它。 可以创建类型的类文件或包。 文件的名称和路径(相对于root output location for class files )基于要声明的项目的名称以及项目的指定模块(如果有)。


2、javapoet

是一款可以自动生成Java文件的第三方开源库,API简单易懂;

build.gradle添加: implementation 'com.squareup:javapoet:1.11.1'

2.1 常用类

TypeSpec————用于生成类、接口、枚举对象的类

MethodSpec————用于生成方法对象的类

ParameterSpec————用于生成参数对象的类

AnnotationSpec————用于生成注解对象的类

FieldSpec————用于配置生成成员变量的类

ClassName————通过包名和类名生成的对象,在JavaPoet中相当于为其指定Class

ParameterizedTypeName————通过MainClass和IncludeClass生成包含泛型的Class

JavaFile————控制生成的Java文件的输出的类

2.2 生成代码

JavaFile.builder(String packageName, TypeSpec typeSpec).builder().writerTo(Filer filer)


3、静态结构包(javax.lang.model.element)

表示程序元素,如模块,包,类或方法。每个元素表示静态的语言级结构(而不是虚拟机的运行时结构)。应使用equals(Object)方法比较元素。不能保证任何特定元素始终由同一个对象表示。要实现基于Element对象类的操作,请使用visitor或使用getKind()方法的结果。使用instanceof不一定是确定有效类的对象在这个造型层次,因为一个实现可以选择让单个对象实现多个可靠的成语Element子接口。

3.1子接口

ExecutableElement,ModuleElement,PackageElement,Parameterizable,QualifiedNameable,TypeElement,TypeParameterElement,VariableElement

3.1.1  VariableElement

表示一个字段,枚举常量,方法或构造函数参数,局部变量,资源变量或异常参数。

方法

Element getEnclosingElement​()

返回此变量的包围元素。方法或构造函数参数的封闭元素是声明参数的可执行文件。

Name getSimpleName​()

返回此变量元素的简单名称。

3.1.2 TypeElement

表示一个类或接口程序元素。提供关于类型及其成员的信息的访问。注意,枚举类型是一种类,注释类型是一种接口。

3.1.3 ExecutableElement

表示类或接口的方法,构造函数或初始化器(静态或实例),包括注释类型元素。


4 javax.lang.model.util.Elements

对程序元素进行操作的实用方法。

PackageElement getPackageOf​(Element type)

返回元素的包。 一个包的包是自己的。

参数 type - 正在检查的元素

结果 一个元素的包装

上一篇 下一篇

猜你喜欢

热点阅读