要在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-lib
JAR中应该有一个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
路径指定用于查找注释处理程序的模块路径。
未提及用于自动检测注释处理器的模块路径。