如何在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"] }