NoSuchBeanDefinitionException при добавлении javax.inject.Provider<T> в конструкторы с использованием Spring
Я использую основанную на конструкторе инъекцию зависимостей, чтобы внедрить javax.inject.Provider<T>
на службу. С Spring Framework (4.2.5), NoSuchBeanDefinitionException
будет брошено сообщение "Не найден квалифицирующий компонент типа [T] для зависимости. Почему T
ожидается весной при введении javax.inject.Provider<T>
?
Вот пример кода:
Поставщик:
import javax.inject.Provider;
public class MessageProvider implements Provider<String> {
@Override
public String get() {
return "Hello!";
}
}
Обслуживание:
import javax.inject.Inject;
import javax.inject.Provider;
public class GreetingService {
private final String message;
@Inject
GreetingService(Provider<String> provider) {
// GreetingService(MessageProvider provider) { // this works!
this.message = provider.get();
}
public String greeting() {
return message;
}
}
Тестовое задание:
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class GreetingServiceTest {
@Test
public void testSomeMethod() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MessageProvider.class);
ctx.register(GreetingService.class);
ctx.refresh();
GreetingService bean = ctx.getBean(GreetingService.class);
String message = bean.greeting();
assertNotNull(message);
}
}
И вот сообщение об ошибке:
Ошибка создания bean-компонента с именем'reetingService ': не удалось создать экземпляр компонента с помощью конструктора; вложенное исключение - org.springframework.beans.BeanInstantiationException: не удалось создать экземпляр [GreetingService]: конструктор сгенерировал исключение; Вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: не найден квалифицирующий компонент типа [java.lang.String] для зависимости: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат для автоматической передачи для этой зависимости. Аннотации зависимостей: {}
1 ответ
Ваш вопрос немного двусмысленный. Вы спрашиваете, зачем Spring нужен бин, который может создать T
или вы спрашиваете, почему Spring не вводит экземпляр вашего MessageProvider
учебный класс?
Если ваш вопрос является первым, то проблема, с которой вы сталкиваетесь, заключается в том, что Provider<T>
это интерфейс, а не класс. Когда вы вводите Provider<String>
Спринг говорит: "Хм, я не вижу никакого определения бина для Provider
интерфейс, есть ли другой способ удовлетворения этой зависимости?"И ответ Spring:" Да, я могу создать экземпляр org.springframework.beans.support.DefaultListableBeanFactory$DependencyProvider
, но только если я знаю, как создать T
то есть есть определение бина для T
".
Ваш пример кода должен работать, если вы добавили класс конфигурации для определения bean-компонента типа String
:
@Configuration
public class MyConfiguration
{
@Bean
public String getMessage()
{
return "Hello!";
}
}
Но если вы спрашиваете, почему Spring не вводит экземпляр вашего MessageProvider
класс, я подозреваю, проблема в том, что он не определен должным образом. Вы можете добавить классификатор к MessageProvider
определение и использование
@Component("MyMessageProvider")
public class MessageProvider implements Provider<String> {
...
а также
@Inject
GreetingService(@Qualifier("MyMessageProvider") Provider<String> provider) {
...
точно сказать, какой Provider
реализация, которую вы хотите ввести.