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

Rom*_*kiy 9 java spring dependency-injection java-9

在我的@Configuration课堂上,我有如下的家属:

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

    // more code
}
Run Code Online (Sandbox Code Playgroud)

在Oracle JDK 8:firstDataSource字段中工作的依赖项注入已成功注入非null值.

现在我尝试在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
Run Code Online (Sandbox Code Playgroud)

但是在JDK 9下,它会在启动期间抛出异常,这是由以下原因造成的:

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

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

Nam*_*man 8

java.xml.ws.annotation在jdk9过时的存在可能是你面对什么样的原因.由于注释@Resource来自javax.annotation同一模块导出的包.

您可能希望提供javatm-common-annotations作为可java.xml.ws.annotation导出javax.annotation 的可升级模块.

这个独立版本的Java(TM)Common Annotations使用Java平台模块系统"自动"模块名称java.annotation来匹配JDK 9中使用的模块名称.

中心的搜索建议,您可以使用: -

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

使用共享代码在我的机器上运行正常.


此外,还有关于您共享的代码的说明.由于您正在迁移到使用JDK9,因此您应该迁移到使用28-9-2017发布的最新springframework依赖: -

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.0.RELEASE</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

编辑:请查看 Roman的答案,以便--add-modules在您不打算迁移到已javaee展开的模块的情况下使用.


Rom*_*kiy 8

添加一些缺少的细节.

弹簧@Resource驱动注射仅javax.annotation.Resource在运行时可用时才有效.春天检查:

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

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

在我的例子中,在JDK 9下,这个类在运行时不可用,因为它属于一个单独的模块java.ws.xml.annotation(与java.base包含的基本模块java.lang和一些总是可用的其他包分开).要解决该问题,可以采取以下方法之一:

  1. javax.annotation-api库添加到我的应用程序类路径中,如@AlanBateman和@nullpointer建议的那样.
  2. 作为替代方案,java可以指示使用命令行开关添加模块:--add-modules java.xml.ws.annotation.这使代码保持不变.