java - 如何在 Java 9 的运行时访问 javax.annotation.Resource

标签 java java-9 java-module

我有一个测试:

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

最佳答案

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

the unnamed module reads package javax.annotation from both java.xml.ws.annotation and 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.annotation 作为 upgradeable module这时候你就可以使用依赖了

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

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


So the required clause by itself it not enough to get access to a module... is this true for all JDK-supplied modules (excluding java.base), or it is only true for deprecated modules?

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


更新 - 使用 JDK/11 或更高版本将不再支持第一个选项,其中 JEP 为 Remove the Java EE and CORBA Modules有针对性。

关于java - 如何在 Java 9 的运行时访问 javax.annotation.Resource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46502001/

相关文章:

java - 如何修复java模块之间的循环依赖?

java - 控制反转、依赖注入(inject)和策略模式以及 Java 中的示例

java - 锁定类是否也锁定类变量? - java

java泛型设计问题(状态机)

java - Java 9 的 LogManager.getLogger()/Logger.getHandlers() 上缺少斜杠似乎会导致异常

java - Java11 中找不到 jdk.incubator.httpclient 模块

java 9 : JLink created invalid images - missing module executable script

java - 聚合 Spring Data Couchbase 存储库方法 - 如何查询给定属性的所有唯一值的列表?

maven - 带有 Maven 的 Java 9 - 找不到模块

java - 如何解决java.lang.NoClassDefFoundError : javax/xml/bind/JAXBException