Весна: внедрение @Resource перестало работать под JDK9

В моем @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 ответа

Решение

java.xml.ws.annotation быть устаревшим в jdk9, возможно, является причиной того, с чем вы сталкиваетесь. Так как аннотация @Resource из пакета javax.annotation экспортируется тем же модулем.

Возможно, вы захотите предоставить javatm-common-annotations в качестве обновляемого модуля для java.xml.ws.annotation который экспортирует javax.annotation.

В этом автономном выпуске Java(TM) Common Annotations используется "автоматическое" имя модуля Java Platform Module System для java.annotation, соответствующее имени модуля, используемому в JDK 9.

Поиск по центральной подсказке, вы можете использовать:-

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

Это нормально работает на моей машине с вашим общим кодом.


Также обратите внимание на код, которым вы поделились. Поскольку вы переходите на использование JDK9, вы должны перейти на использование новейших зависимостей Springframework, выпущенных 28-9-2017:

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

Изменить: Посмотрите на ответ Романа для альтернативы, чтобы использовать --add-modules если вы не планируете переходить на javaee взорвался модуль еще.

Добавляем несколько недостающих деталей.

весна @Resourceвпрыск работает только тогда, когда javax.annotation.Resource доступно во время выполнения. Весна делает проверку:

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 библиотека к моему classpath приложения, как предложили @AlanBateman и @nullpointer.
  2. Как альтернатива, java может быть дано указание добавить модуль с помощью переключателя командной строки: --add-modules java.xml.ws.annotation, Это оставляет код без изменений.
Другие вопросы по тегам