使用Spring将javax.inject.Provider <t>注入构造函数时的NoSuchBeanDefinitionException

时间:2016-05-04 22:58:38

标签: java spring dependency-injection jsr330

我正在使用基于构造函数的依赖注入向服务注入javax.inject.Provider<T>。使用Spring Framework(4.2.5),将抛出NoSuchBeanDefinitionException说“没有找到类型[T]的限定bean用于依赖。为什么注入T时Spring会期望javax.inject.Provider<T>?” / p>

以下是示例代码:

提供者:

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);
    }

}

这是错误信息:

  

创建名为'greetingService'的bean时出错:通过构造函数的Bean实例化失败;嵌套异常是org.springframework.beans.BeanInstantiationException:无法实例化[GreetingService]:构造函数抛出异常;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为[java.lang.String]的限定bean:期望至少有一个bean符合此依赖关系的autowire候选资格。依赖注释:{}

1 个答案:

答案 0 :(得分:0)

你的问题有点含糊不清。您是否在问为什么Spring需要一个可以创建T的bean,或者您是在问为什么Spring没有注入MessageProvider类的实例?

如果您的问题是前者,那么您面临的问题是Provider<T>是一个接口,而不是一个类。当你注入Provider<String> Spring说,“嗯,我没有看到Provider接口的任何bean定义,还有另一种方法可以满足这种依赖吗?” Spring的答案是,“是的,我可以创建org.springframework.beans.support.DefaultListableBeanFactory$DependencyProvider的实例,但前提是我知道如何创建T,即T有一个bean定义。”

如果您添加了一个配置类来定义类型为String的bean,那么您的示例代码应该有效:

@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实现。