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