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

时间:2017-09-29 17:58:21

标签: java spring dependency-injection java-9

在我的@Configuration课程中,我有以下内容:

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

    // more code
}

在Oracle JDK 8中使用依赖注入: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

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

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

在未注入依赖项时发生。

2 个答案:

答案 0 :(得分:7)

jdk9中不推荐使用的java.xml.ws.annotation可能是你所面临的原因。由于注释@Resource来自同一模块导出的包javax.annotation

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

  

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

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

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

使用共享代码在我的计算机上运行正常。

此外,还有关于您共享的代码的说明。由于您要迁移到使用JDK9,因此您应该迁移到使用最新的springframework依赖项released as on 28-9-2017: -

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

修改 :如果您不打算迁移到--add-modules,请查看Roman's answer以便使用javaee {{1}}已展开的模块。

答案 1 :(得分:6)

添加一些缺失的细节。

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下,此类在运行时不可用,因为它属于单独的模块java.ws.xml.annotation(与包含java.base的基本java.lang模块分开其他总是可用的包。要解决该问题,可以采取以下方法之一:

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