使用注释处理器内的ServiceLoader

问题描述 投票:3回答:2

是否有可能从注释处理器的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)方法称为另一个项目的构建的一部分,它没有列出任何服务。

有没有一种方法,使这项工作?

java annotation-processing serviceloader
2个回答
7
投票

问题是使用的ServiceLoader时Thread.currentThread().getContextClassLoader()未指定类加载器,其不能从注释处理器内看到META-INF\services文件,但可以从main方法。

使用ServiceLoader.load(Service.class, AnnotationProcessor.class.getClassLoader())正确地从AnnotationProcessor中加载的服务。

(随意添加到我的回答如果你知道为什么ContextClassLoader看不到META-INF\services


0
投票

如果您打算运行的Java模块系统的注释处理器:

在我看来,对于Java 11 javac编译器不完全模块感知。我成功了正确设置javac用于注释处理利用--module-path,但加载插件通过ServiceLoader成以同样的方式我的注释处理器竟然是不可能的。后因此非常过长...时间摆弄周围所有可能样的编译器选项,我在通过加载模块路径的处理器,并通过类路径加载服务的混合方式结束了。

所有的一切,都需要执行以下步骤对我来说(我直接工作的javac命令行上):

  1. 用正确的module-info.javauses声明两种,注释处理器和服务适当provided with设置要加载
  2. 通过非默认ServiceLoader加载ClassLoader(参见bnorm的答案)
  3. 提供META-INF/services文件被加载服务
  4. 通过-classpath(或-processorpath)指定路径服务
© www.soinside.com 2019 - 2024. All rights reserved.