是否有可能从注释处理器的ServiceLoader
方法中使用init(ProcessingEnvironment)
?
interface Service {}
class AnnotationProcessor extends AbstractProcessor {
public static void main(String[] args) {
ServiceLoader<Service> loader = ServiceLoader.load(Service.class);
System.out.println("Found Services:");
for (Service service : loader) {
System.out.println(service);
}
}
@Override
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
ServiceLoader<Service> loader = ServiceLoader.load(Service.class);
System.out.println("Found Services:");
for (Service service : loader) {
System.out.println(service);
}
}
...
}
运行的主要方法产生我在META-INF / services文件中指定的服务。然而,当init(ProcessingEnvironment)
方法称为另一个项目的构建的一部分,它没有列出任何服务。
有没有一种方法,使这项工作?
问题是使用的ServiceLoader时Thread.currentThread().getContextClassLoader()
未指定类加载器,其不能从注释处理器内看到META-INF\services
文件,但可以从main
方法。
使用ServiceLoader.load(Service.class, AnnotationProcessor.class.getClassLoader())
正确地从AnnotationProcessor中加载的服务。
(随意添加到我的回答如果你知道为什么ContextClassLoader看不到META-INF\services
)
如果您打算运行的Java模块系统的注释处理器:
在我看来,对于Java 11 javac
编译器不完全模块感知。我成功了正确设置javac
用于注释处理利用--module-path
,但加载插件通过ServiceLoader
成以同样的方式我的注释处理器竟然是不可能的。后因此非常过长...时间摆弄周围所有可能样的编译器选项,我在通过加载模块路径的处理器,并通过类路径加载服务的混合方式结束了。
所有的一切,都需要执行以下步骤对我来说(我直接工作的javac
命令行上):
module-info.java
和uses
声明两种,注释处理器和服务适当provided with
设置要加载ServiceLoader
加载ClassLoader
(参见bnorm的答案)META-INF/services
文件被加载服务-classpath
(或-processorpath
)指定路径服务