- 所有已知的实现类:
AbstractProcessor
注释处理发生在 回合 序列中。在每一轮中,可能会要求处理器process在前一轮生成的源文件和类文件上找到的注释子集。第一轮处理的输入是工具运行的初始输入;这些初始输入可以被视为虚拟第零轮处理的输出。如果处理器被要求在给定的轮次上进行处理,它将被要求在后续轮次中进行处理,包括最后一轮,即使没有要处理的注释也是如此。工具基础结构还可以要求处理器处理由工具操作隐式生成的文件。
Processor
的每个实现都必须提供一个公共的无参数构造函数,供工具用来实例化处理器。工具基础设施将与实现此接口的类交互,如下所示:
- 如果未使用现有的
Processor
对象,则为创建处理器实例,该工具将调用处理器类的无参数构造函数。 - 接下来,该工具使用适当的
ProcessingEnvironment
调用init
方法。 - 之后,该工具调用
getSupportedAnnotationTypes
、getSupportedOptions
和getSupportedSourceVersion
。这些方法每次运行只调用一次,而不是每一轮。 - 该工具会根据需要调用
Processor
对象上的process
方法;为每一轮创建一个新的Processor
对象not。
该工具使用发现过程找到注解处理器并决定它们是否应该运行。通过配置该工具,可以控制一组潜在的处理器。例如,对于 JavaCompiler
要运行的候选处理器列表可以是 直接设置 或由用于 service-style 查找的 搜索路径 控制。其他工具实现可能有不同的配置机制,例如命令行选项;有关详细信息,请参阅特定工具的文档。该工具向 run 询问的处理器是 根元素 上的注释 present 接口的函数,处理器支持的注解接口 是什么,以及是否是处理器 声明它处理的注解接口。处理器将被要求处理它支持的注释接口的一个子集,可能是一个空集。对于给定的轮次,该工具计算存在于包含在根元素中的元素上的注释界面集。如果存在至少一个注释接口,那么当处理器声明注释接口时,它们将从一组不匹配的注释接口中删除。当该集合为空或没有更多处理器可用时,该回合已运行完毕。如果不存在注解接口,注解处理仍会发生,但仅通用处理器它支持处理所有注释接口,"*"
,可以声明(空)注释接口集。
如果包含在轮的根元素中的元素上存在该接口的至少一个注释,则认为该注释接口存在。为此,类型参数被认为包含在它的 通用元素 中。为此,包元素not被认为是将顶级类和接口包含在该包中。 (代表包的根元素在处理 package-info
文件时创建。)同样,出于此目的,模块元素 not 被视为将包包含在该模块中。 (代表模块的根元素是在处理 module-info
文件时创建的。)在计算是否存在注释接口时,将忽略 类型用途 上的注释,而不是元素上的注释。
如果注释符合 AnnotatedConstruct
中给出的存在定义,则注释为 present。简而言之,如果注释直接存在或通过继承存在,则出于发现的目的,注释被视为存在。注释被 not 认为是存在的,因为它被容器注解包装了。在操作上,当且仅当它包含在对该元素调用的 Elements.getAllAnnotationMirrors(Element)
的结果中时,这等同于存在于元素上的注释。由于容器注解内的注释不被视为存在,为了正确处理 可重复的注解接口 ,建议处理器在处理器的 支持的注解接口 集中包含可重复注释接口及其包含的注释接口。
请注意,如果处理器支持 "*"
并返回 true
,则声明所有注释。因此,例如,用于执行附加有效性检查的通用处理器应返回false
,以免阻止其他此类检查器能够运行。
如果处理器抛出未捕获的异常,该工具可能会停止其他活动的注解处理器。如果处理器引发错误,则当前轮次将运行完成,后续轮次将指示 出现错误 。由于注解处理器在协作环境中运行,因此处理器应该仅在错误恢复或报告不可行的情况下抛出未捕获的异常。
工具环境不需要支持以多线程方式访问环境资源的注解处理器,每轮 或 跨轮。
如果返回有关注解处理器的配置信息的方法返回 null
、返回其他无效输入或抛出异常,则工具基础结构必须将此视为错误条件。
为了在不同的工具实现中运行时变得健壮,注解处理器应该具有以下属性:
- 处理给定输入的结果不是其他输入存在与否的函数(正交性)。
- 处理相同的输入会产生相同的输出(一致性)。
- 处理输入A接着是处理输入B相当于处理B然后A(交换性)
- 处理输入不依赖于其他注解处理器输出的存在(独立性)
Filer
接口讨论了对处理器如何操作文件的限制。
- API 注意:
-
此接口的实现者可能会发现扩展
AbstractProcessor
比直接实现此接口更方便。 - 自从:
- 1.6
-
方法总结
修饰符和类型方法描述Iterable<? extends Completion>
getCompletions
(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) 向工具基础结构返回对注释的建议完成的可迭代。返回此处理器支持的注解的名称。返回此处理器识别的选项。返回此注解处理器支持的最新源版本。void
init
(ProcessingEnvironment processingEnv) 使用处理环境初始化处理器。boolean
process
(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) 处理来自前一轮的 根元素 上的一组注释接口,并返回此处理器是否声明这些注释接口。
-
方法详情
-
getSupportedOptions
返回此处理器识别的选项。处理工具的实现必须提供一种方法来传递特定于处理器的选项,这与传递给工具本身的选项截然不同,请参阅getOptions
。集合中返回的每个字符串必须是句点分隔的 身份标识 序列:
- 支持的选项字符串:
- 身份标识
- 身份标识:
- Identifier
-
Identifier
.
身份标识 - 标识符:
- 句法标识符,包括关键字和文字
工具可能会使用此信息来确定用户提供的任何选项是否未被任何处理器识别,在这种情况下,它可能希望报告警告。
- 返回:
- 此处理器识别的选项或空集(如果没有)
- 参见:
-
getSupportedAnnotationTypes
返回此处理器支持的注释接口的名称。结果的一个元素可以是受支持的注释接口的规范(完全限定)名称。或者,它可以采用“name.*
”形式,表示所有具有以“name.
”开头的规范名称的注释接口的集合。在这两种情况中的任何一种情况下,注释接口的名称前面都可以有选择地加上模块名称,后跟一个"/"
字符。例如,如果处理器支持"a.B"
,这可以包括多个名为a.B
的注释接口,它们位于不同的模块中。要在foo
模块中仅支持a.B
,请改用"foo/a.B"
。如果包含模块名称,则仅匹配该模块中的注释。特别是,如果在不支持模块的环境中给出模块名称,例如为源版本没有模块配置的注释处理环境,则具有模块名称的注释接口与not匹配。最后,"*"
本身代表所有注释接口的集合,包括空集。请注意,处理器不应声明"*"
,除非它实际上正在处理所有文件;声明不必要的注释可能会导致某些环境中的性能下降。集合中返回的每个字符串必须被以下语法接受:
- 支持的注释类型字符串:
- ModulePrefix选择 TypeName DotStar选择
*
- 模块前缀:
- ModuleName
/
- 点星:
.
*
- API 注意:
-
在支持模块的环境中运行时,鼓励处理器在描述其支持的注释接口时包含模块前缀。
AbstractProcessor.getSupportedAnnotationTypes
方法支持在没有模块的环境中运行时剥离模块前缀。 - 返回:
- 此处理器支持的注解的名称,如果没有则为空集
- 看Java 语言规范:
-
3.8 标识符
- 参见:
-
getSupportedSourceVersion
SourceVersion getSupportedSourceVersion()返回此注解处理器支持的最新源版本。- 返回:
- 此注解处理器支持的最新源版本
- 参见:
-
init
使用处理环境初始化处理器。- 参数:
processingEnv
- 工具框架为处理器提供的设施环境
-
process
处理来自前一轮的 根元素 上的一组注释接口,并返回此处理器是否声明这些注释接口。如果返回true
,说明注解接口已经被声明,不会要求后续处理器处理;如果返回false
,则注解接口未声明,可能会要求后续处理器处理它们。处理器可能始终返回相同的boolean,也可能根据自己选择的标准改变结果。如果处理器支持
"*"
并且根元素没有注释,则输入集将为空。Processor
必须优雅地处理一组空注释。- 参数:
annotations
- 请求处理的注解接口roundEnv
- 当前和前一轮信息的环境- 返回:
- 该处理器是否声明了注解集
-
getCompletions
Iterable <? extends Completion > getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) 向工具基础结构返回对注释的建议完成的可迭代。由于要求完成,因此提供的有关注释的信息可能不完整,就像源代码片段一样。处理器可能会返回一个空的可迭代对象。注解处理器应该集中精力为注解成员提供处理器已知的附加有效性约束的补全,例如int
成员,其值应介于 1 和 10 之间,或者应由已知语法识别的字符串成员,例如正则表达式或 URL。由于正在对不完整的程序建模,因此某些参数可能只有部分信息或者可能是
null
。element
和userText
中至少有一个必须是非null
。如果element
是非null
,则annotation
和member
可能是null
。如果某些参数是null
,处理器可能不会抛出NullPointerException
;如果处理器根据提供的信息没有可提供的完成,则可以返回一个空的可迭代对象。处理器也可能返回一个带有空值字符串的完成和一条描述为什么没有完成的消息。完成是提供信息的,可能反映注解处理器执行的额外有效性检查。例如,考虑简单的注解:
@MersennePrime { int value(); }
AnnotationMirror
,可以返回int
范围内所有此类素数的列表,而无需检查getCompletions
的任何其他参数:import static javax.annotation.processing.Completions.*; ... return List.of(
of
("3"), of("7"), of("31"), of("127"), of("8191"), of("131071"), of("524287"), of("2147483647"));return List.of(
of
("3", "M2"), of("7", "M3"), of("31", "M5"), of("127", "M7"), of("8191", "M13"), of("131071", "M17"), of("524287", "M19"), of("2147483647", "M31"));userText
可用,则可以检查它是否只有一部分 Mersenne 素数有效。例如,如果用户输入@MersennePrime(1
userText
的值将是"1"
;并且只有两个素数是可能完成的:return Arrays.asList(of("127", "M7"), of("131071", "M17"));
@MersennePrime(9
return Collections.emptyList();
return Arrays.asList(of("", "No in-range Mersenne primes start with 9"));
- 参数:
element
- 被注释的元素annotation
- 应用于元素的(可能是部分的)注解member
- 返回可能完成的注解成员userText
- 待完成的源代码文本- 返回:
- 注释的建议补全
-