【问题标题】:How to get access to javax.annotation.Resource at run time in Java 9如何在 Java 9 的运行时访问 javax.annotation.Resource
【发布时间】:2017-09-30 10:51:04
【问题描述】:

我有一个测试:

public class ResourceTest {
    @Test
    public void test() throws ClassNotFoundException {
        Class.forName("javax.annotation.Resource");
    }
}

它尝试访问javax.annotation.Resource。在 java 8 中它可以工作,但在 java 9(我使用的是 Oracle JDK 9)中它失败了 ClassNotFoundException。 正如这里所解释的 Spring: @Resource injection stopped working under JDK9 ,来自 JDK 的 javax.annotation.Resource 在 Java 9 中默认不可用。

我正在尝试使用模块描述符访问它:

module test {
    requires java.xml.ws.annotation;
    requires junit;
}

在这里,我特别请求访问java.xml.ws.annotation 模块(其中包含javax.annotation.Resource)。但是测试还是失败了。

当我删除 requires 子句并添加包含 javax.annotations.Resource 的依赖项(作为库)时,它可以工作:

    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.1</version>
    </dependency>

当我同时添加它们(pom.xmlrequires java.xml.ws.annotation 中的 Maven 依赖项)时,IDEA 中的编译失败并显示以下消息:

the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation

但是 Maven 构建仍然成功!

如果我通过命令行添加 java.xml.ws.annotation 模块,它可以工作(没有 Maven 依赖和 with requires 子句):

mvn clean test -DargLine="--add-modules java.xml.ws.annotation"

我的模块描述有问题吗?如何在没有命令行开关的情况下访问 JDK 提供的 javax.annotation.Resource

测试项目可在https://github.com/rpuch/test-resource-jdk9获取

【问题讨论】:

  • 只添加--add-modules argline 然后requires &lt;modulename&gt; 会发生什么?
  • @nullpointer 在这种情况下测试成功运行(成功找到类)。
  • java.xml.ws.annotation 模块已弃用,无法移除。您应该只根据独立版本查看,这意味着 requires java.annotation 和 Maven 对 javax.annotation/javax.annotation-api/1.3.1 的依赖,就像您所做的那样。这也消除了 --add-modules 的使用。

标签: java java-9 java-module


【解决方案1】:

只是为了消除这里的一些混乱。您在问题中陈述的工作方式是替代方法,不应像您已经看到的那样组合。

未命名的模块从两者中读取包 javax.annotation java.xml.ws.annotation 和 java.annotation


所以它的工作方式是:

您可以使用编译器参数添加模块

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.7.0</version>
    <configuration>
        <release>9</release>
        <compilerArgs>
            <arg>--add-modules</arg>
            <arg>java.xml.ws.annotation</arg>
        </compilerArgs>
    </configuration>
</plugin>

利用javax.xml.ws.annotationupgradeable module,此时您可以使用依赖项

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>

理想情况下,这将是一个更可取的选择,因为前者只是使用标记为forRemoval@Deprecated 模块的替代方案。


因此,required 子句本身不足以访问 模块...对于所有 JDK 提供的模块(不包括 java.base),还是仅适用于已弃用的模块?

不,requires 只是声明的一部分。 [想一想,在 JDK 9 之前,如果你在你的类中使用了一个未被添加为库(类路径)的语句 import some.foo.bar;,那会起作用吗?]。标记为必需的模块必须位于模块路径上,您才能访问它。


更新 - 第一个选项将不再支持使用 JDK/11 或更高版本,其中以 Remove the Java EE and CORBA Modules 为目标的 JEP。 p>

【讨论】:

  • 所以 required 子句本身不足以访问模块...对于所有 JDK 提供的模块(不包括 java.base)都是如此,还是仅适用于不推荐使用的模块?
  • 更新了这个答案。
  • 第一个选项对我有用。 (没有尝试第二个选项)
  • javax.annotation 和其他 JavaEE 类计划在 Java 11 中删除,根据 JEP-320,因此第一个选项将不再适用于 never 版本。
  • 非常感谢分享这个解决方案。对于 java 8,第二个选项(直接依赖)对我有用。
【解决方案2】:

对于 gradle build,将以下内容添加到 build.gradle 中:

compile 'javax.annotation:jsr250-api:1.0'

tasks.withType(AbstractCompile) {
    options.compilerArgs += ["--add-modules", "java.xml.bind"]
}

tasks.withType(Test) {
    jvmArgs += ["--add-modules", "java.xml.bind"]
}

【讨论】:

    猜你喜欢
    • 2017-08-11
    • 1970-01-01
    • 2019-03-08
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    相关资源
    最近更新 更多