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 реализация, которую вы хотите ввести.

Другие вопросы по тегам