无法在注释处理器中装入资源(不在类路径上)

2022-09-02 22:43:12

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

接口驻留在

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

我想验证驻留的属性文件,如果它们确实包含生成的枚举中定义的键。MyProject/src/main/resources/META-INF/resource-bundle/

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

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

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

有没有人遇到过这样的问题,任何人都可以给我一个线索,告诉我如何为处理器提供资源?

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

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

谢谢。


答案 1

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

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

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

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

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

    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
    //...
}

编辑:

我感觉很多人都遇到了Eclipse中的资源问题,这些资源没有使用注释处理器加载它们(抛出一个异常)。src/main/resourcesFiler

事实上,Eclipse不会加载资源是一个众所周知的问题。我上面展示的类路径黑客可能会也可能不会起作用,并且更多地适用于处理器正在使用的其他库(因为它们已经与资源一起编译)。target/classes

解决方案(如果可以这样称呼)是加载文件,就像它们是普通文件一样。这需要通过一些技巧来猜测项目结构

您可以告诉 Eclipse 用户只需将资源放入 。src/main/java


答案 2

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


推荐