Java 11模块信息:如何注册注释处理器



要在Java 11中注册服务提供商,可以使用以下"provides"模块信息条目:

module com.mycompany.mylib {
provides ServiceInterface with ServiceImpl;
}

然而,对于注释处理器,这似乎不起作用。(注释处理器的特殊之处在于,编译器应该在编译时获取实现,而不是在运行时获取应用程序。(

为了测试这一点,我在GitHub上创建了一些SSCCE。

共有2个模块:

  • java11-sample-annotation-processor:提供@Foo注释和FooApplicationProcessor
  • java11-sample-lib:提供2个示例类,均使用@Foo注释

预期输出:java11-sample-libJAR中应该有一个foo.txt文件

主分支中的版本是工作的版本

  • Java 11
  • 未使用module-info
  • src/main/resources/META-INF/services/javax.annotation.processing.Processor中的注释处理器注册

在以下版本中,不会生成foo.txt文件:

在模块信息中的注册分支中,我将2个库更改为带有模块信息的Java 11模块。注释处理器在这里注册在模块信息中:

import com.github.puce77.java11annotationprocessortest.annotation.impl.FooApplicationProcessor;
module com.github.puce77.java11annotationprocessortest.annotation {
exports com.github.puce77.java11annotationprocessortest.annotation;
provides javax.annotation.processing.Processor with FooApplicationProcessor;
requires java.compiler;
}

模块信息moduleAndPkg分支中的注册是一个轻微的变化,我指定了目标模块和目标包(硬编码(,而不是根包。

在注册中,meta-inf分支仍然都有模块信息,但注释处理器注册在src/main/resources/META-INF/services/javax.annotation.processing.Processor中,而不是模块信息中(以防编译器无法使用模块信息中的provides语句!?(

在仅有的一个模块分支中,我再次从java11-sample-annotation-processor中删除了模块信息。注释处理器注册在src/main/resources/META-INF/services/javax.annotation.processing.Processor中。

因此,我的问题是:在使用Java 11模块时,如何配置注释处理器?

过去,注释处理器在编译过程中放置在类路径上时会自动检测到。您可以从javac:的文档中看到这一点

--class-path路径-classpath通道-cp通路

指定在何处查找用户类文件和注释处理器[emphasis added]。该类路径覆盖CLASSPATH环境变量中的用户类路径。

  • 如果未指定--class-path-classpath-cp,则用户类路径为CLASSPATH环境变量的值(如果已设置(,否则为当前目录
  • 如果未编译模块的代码,如果未指定--source-path-sourcepath选项,则还会在用户类路径中搜索源文件
  • 如果未指定-processorpath选项,则还会搜索注释处理器的类路径 [emphasis added]

[…]

--processor-path路径-processorpath通道

指定在何处查找注释处理程序如果不使用此选项,则在类路径中搜索处理器[emphasis added]

只要使用类路径,情况仍然如此。但是,当使用模块路径时,情况并非如此。对于要检测的模块化注释处理器,您必须用另一个选项明确指出它们:

--module-path路径-p通道

指定在何处查找应用程序模块。

[…]

--processor-module-path路径

指定用于查找注释处理程序的模块路径。

未提及用于自动检测注释处理器的模块路径。

最新更新