如何在Java 9中运行时访问javax.annotation.Resource

Rom*_*kiy 20 java java-9 java-module

我有一个测试:

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

它试图访问javax.annotation.Resource.在java 8中它可以工作,但是在java 9中(我使用的是Oracle JDK 9)它失败了ClassNotFoundException.正如本文所解释的那样:@Resource注入在JDK9下停止工作,javax.annotation.ResourceJDK在Java 9中默认不可用.

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

module test {
    requires java.xml.ws.annotation;
    requires junit;
}
Run Code Online (Sandbox Code Playgroud)

在这里,我特意请求访问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>
Run Code Online (Sandbox Code Playgroud)

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

the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation
Run Code Online (Sandbox Code Playgroud)

但Maven构建仍然成功!

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

mvn clean test -DargLine="--add-modules java.xml.ws.annotation"
Run Code Online (Sandbox Code Playgroud)

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

测试项目可在https://github.com/rpuch/test-resource-jdk9上找到

Nam*_*man 29

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

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


所以它的工作方式是:

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

<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>
Run Code Online (Sandbox Code Playgroud)

要么

利用的javax.xml.ws.annotation是一个升级模块是当你可以使用依赖

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

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


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

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


更新 - 使用JDK/11或更高版本时,不再支持第一个选项,其中目标是删除Java EE和CORBA模块的JEP.

  • 根据[JEP-320](http://openjdk.java.net/jeps/320)计划在Java 11中删除javax.annotation和其他JavaEE类,因此第一个选项将不再适用于never版本. (2认同)