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

2022-09-01 17:13:24

我有一个测试:

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

它尝试访问 。在java 8中,它有效,但在java 9中(我使用的是Oracle JDK 9),它以.正如这里所解释的 春天:@Resource注入在JDK9下停止工作,在Java 9中默认不可用。javax.annotation.ResourceClassNotFoundExceptionjavax.annotation.Resource

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

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

在这里,我专门请求访问模块(其中包含)。但测试仍然失败。java.xml.ws.annotationjavax.annotation.Resource

当我删除该子句并添加一个包含 的依赖项(作为库)时,它的工作原理是:requiresjavax.annotations.Resource

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

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

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

但是Maven构建仍然成功!

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

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

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

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


答案 1

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

未命名的模块从java..xml.ws.annotation和java.annotation中读取javax.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

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

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


因此,必需的子句本身不足以访问模块...对于所有 JDK 提供的模块(不包括 java.base),还是只适用于不推荐使用的模块?

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


更新 - 使用 JDK/11 或更高版本时,第一个选项将不再受支持,其中 JEP 以除去 Java EE 和 CORBA 模块为目标。


答案 2

对于 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"]
}

推荐