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

我有一个测试:

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注入在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的依赖项(作为库)时,它可以工作:

   javax.annotation javax.annotation-api 1.3.1  

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

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

但Maven构建仍然成功!

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

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

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

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

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

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


所以它的工作方式是:

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

  org.apache.maven.plugins maven-compiler-plugin 3.7.0  9  --add-modules java.xml.ws.annotation    

要么

使用javax.xml.ws.annotation作为可升级的模块 ,当您可以使用依赖项时

  javax.annotation javax.annotation-api 1.3.1  

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


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

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


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

对于gradle构建,将以下内容添加到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"] }