18

我有一个注释处理器,它将使用接口的 getter 方法定义的键生成一个枚举。

该接口位于

MyProject/src/main/java/my.package.MyInterfaces.java。

我想验证驻留在其中的属性文件MyProject/src/main/resources/META-INF/resource-bundle/是否包含生成的枚举中定义的键。

我的问题是属性文件不能通过处理器的类加载器或 Filer.getResource(...) 获得。

  • 如何使该项目的源代码或类路径可供处理器使用,以便我可以加载属性文件?

  • 现在我只有处理器所在的 jar 中的资源可用。我确实尝试通过 eclipse Project/Properties/Java compiler/Annotation processing/Processor 选项定义 -classpath 和/或 -sourcepath 但它没有成功。

有没有人遇到过这样的问题,谁能给我一个线索,告诉我如何让处理器可以使用这些资源?

我确实有 maven 结构但不使用 maven,因为应用程序中有旧的依赖项。所以maven现在不是我的选择。

Eclipse 3.6 Helios 似乎StandardLocation.SOURCE_PATHStandardLocation.CLASS_PATH没有在 Filer#getResource() 中实现,因此将生成的源或类文件写入SOURCE_PATHCLASS_PATH似乎是不可能的,还可以访问SOURCE_PATHCLASS_PATH*上的任何文件

谢谢。

4

3 回答 3

2

问题是绑定到当前线程 ( ) 的 ClassLoader在调用Thread.currentThread().getContextClassLoader()时不是 URLClassLoader 。Processor#process它似乎是一个不允许加载资源的受限类加载器。这发生在 javac、eclipse 编译器、maven 编译器等。

幸运的是,您的处理器类将有一个适当的 ClassLoader 绑定到它(即getClass().getClassLoader())。

问题是大多数实用程序都希望将正确的 ClassLoader 绑定到线程(最值得注意的是 ServiceLoader 和 ResourceBundles)。

因此,有一个解决方法。当您的处理器执行时,您可以将 ClassLoader 重新绑定到当前线程:

@Override
public boolean process(
        Set<? extends TypeElement> annotations,
        RoundEnvironment roundEnv) {

    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
    //...
}
于 2019-05-05T12:43:58.633 回答
0

作为一种解决方法,您可以尝试通过命令行参数 -Xboothclasspath/a:path 添加需要使用的类路径,/a 会将路径中的值附加到引导类路径。您需要将此作为命令行选项添加到实际的注释处理运行中,因此在 Eclipse 中将是:右键单击项目,选择属性,Java 编译器,注释处理,单击表中的新建并添加键 -Xbootclasspath/a 和添加为值的路径。恐怕我还没有尝试过注释处理,但值得一试!

于 2017-09-07T19:27:31.800 回答
-1

我的问题是无法通过处理器的类加载器或通过Filer.getResource(...).

我不确定我是否理解您的问题。但也许这里的东西会有所帮助。

如何使该项目的源代码或类路径可供处理器使用,以便我可以加载属性文件?

您需要src/main/resources在 Eclipse 中将其添加为“源文件夹”。首先Configure Build Path在 Eclipse 中选择您的 Java 项目。然后选择Source选项卡并单击Add Folder。您应该能够选择src/main/resources文件夹并单击Ok。您现在应该src/main/resources在 Source Folders 列表中看到 。

如果您查看您的target/classes目录,您应该会看到其中的资源目录中的所有文件,这让您知道它们已正确复制到类路径中。

# files in the src main resources
> ls src/main/resources/x/y/z
jgroups_udp.xml
# should compile into target/classes
> ls target/classes/x/y/z
jgroups_udp.xml org
# and should show up in the jar
> -tvf target/project.jar 
   0 Thu Nov 03 18:50:00 EDT 2016 META-INF/
 135 Thu Nov 03 18:49:58 EDT 2016 META-INF/MANIFEST.MF
 ...
3036 Thu Nov 03 18:49:36 EDT 2016 x/y/z/jgroups_udp.xml

然后在您的代码中,您可以通过执行以下操作来引用该文件。这将从类路径的顶部加载文件。如果它在子目录中,那么您将使用以下命令:

InputStream stream =
    getClass().getClassLoader().getResourceAsStream("x/y/z/jgroups_udp.xml");

顺便说一句,如果您使用的是maven,您会向您添加以下内容pom.xml

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>
于 2016-11-03T22:57:21.237 回答