Spring: @Resource 注入在 JDK9 下停止工作

Spring: @Resource injection stopped working under JDK9

在我的 @Configuration class 中,我有如下依赖关系:

@Configuration
public class MyConfig {
    @Resource(name = "firstDataSource")
    private DataSource firstDataSource;

    // more code
}

依赖项注入在 Oracle JDK8 中有效:firstDataSource 字段已成功注入非空值。

现在我尝试 运行 JDK 9 中的应用程序(没有修改)。结果是 @Resource 不再触发依赖注入:用这个注释注释的所有内容仍然是 null.

@Resource 停止工作的原因可能是什么?

Spring项目中使用的是4.0.9

这是一个演示问题的测试项目:https://github.com/rpuch/test-spring-injection-jdk9

它包含一个测试:MainTest,我 运行 来自我的 IDE。当我使用 JDK 8 时,它输出

сен 29, 2017 10:45:13 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f8ed237: startup date [Fri Sep 29 22:45:13 SAMT 2017]; root of context hierarchy
OK

但是在JDK9下,启动时抛出异常,原因如下:

Caused by: java.lang.IllegalStateException: bean1 is not injected
    at Bean2.<init>(Bean2.java:7)
    at Config2.bean2(Config2.java:16)

当没有注入依赖项时会发生这种情况。

jdk9 中弃用的 java.xml.ws.annotation 可能是您所面临问题的原因。由于注释 @Resource 来自同一模块导出的包 javax.annotation

您可能想要提供 javatm-common-annotations as an upgradeable module for java.xml.ws.annotation 导出 javax.annotation.

This standalone release of Java(TM) Common Annotations uses a Java Platform Module System "automatic" module name of java.annotation, to match the module name used in JDK 9.

central suggests上的搜索,可以使用:-

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

使用您的共享代码,这在我的机器上运行良好。


此外,关于您共享的代码的说明。由于您正在迁移到使用 JDK9,因此您应该迁移到使用最新的 springframework dependencies released as on 28-9-2017:-

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.0.RELEASE</version>
</dependency>

Edit :请​​查看 以了解如何使用 --add-modules如果您还不打算迁移到 javaee 展开的模块。

添加一些缺失的细节。

Spring @Resource 驱动的注入仅在 javax.annotation.Resource 在 运行 时间可用时才有效。 Spring 检查:

private static final boolean jsr250Present =
        ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());

然后使用那个 jsr250Present 变量来查看是否应该启用基于 @Resource 的注入(以及 @PostConstruct/@PreDestroy 功能)。

就我而言,在 JDK 9 下,此 class 在 运行 时间内不可用,因为它属于一个单独的模块 java.ws.xml.annotation(与基本模块分开java.base 模块包含 java.lang 和其他一些始终可用的包)。为了解决这个问题,可以采取以下方法之一:

  1. 按照@AlanBateman 和@nullpointer 的建议,将javax.annotation-api 库添加到我的应用程序class路径中。
  2. 作为替代方案,可以指示 java 使用命令行开关添加模块:--add-modules java.xml.ws.annotation。这使代码完好无损。