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