是否可以在注释处理器的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);
}
}
...
}
运行main方法会生成我在META-INF / services文件中指定的服务。但是,当init(ProcessingEnvironment)
方法作为另一个项目的构建的一部分被调用时,它不会列出任何服务。
有没有办法让这项工作?
答案 0 :(得分:6)
问题是ServiceLoader在未指定ClassLoader时使用Thread.currentThread().getContextClassLoader()
,但无法从注释处理器中查看META-INF\services
文件,但可以使用main
方法。
使用ServiceLoader.load(Service.class, AnnotationProcessor.class.getClassLoader())
从AnnotationProcessor中正确加载服务。
(如果你知道为什么ContextClassLoader看不到META-INF\services
,请随意添加我的答案)
答案 1 :(得分:0)
如果您打算在 Java模块系统上运行注释处理器:
在我看来,对于Java 11,javac
编译器并不完全支持模块。我成功使用javac
正确设置了--module-path
进行注释处理,但是事实证明,通过ServiceLoader
以同样的方式将插件加载到注释处理器中是不可能的。因此,在花了很长时间研究所有可能的编译器选项之后,我最终以一种混合方式通过模块路径加载处理器并通过类路径加载服务。
总而言之,我需要执行以下步骤(我直接在javac
命令行上工作):
module-info.java
和uses
正确设置provided with
注释处理器和服务的声明
被加载ServiceLoader
加载ClassLoader
(请参阅bnorm的答案)META-INF/services
文件以加载服务-classpath
(或-processorpath
)指定服务路径