2017-01-05 63 views
4

简单的测试类显示我的问题:Spring无法解析List类型的bean的@Bean依赖项?

import java.util.ArrayList; 
import java.util.List; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = SpringTest.OptionalConfiguration.class) 
public class SpringTest { 
    static class Item extends Object {} 

    @Configuration 
    static class OptionalConfiguration { 
     @Bean 
     List<Item> someString() { 
      return new ArrayList<>(); 
     } 
     @Bean 
     Object foo(List<Item> obj) { 
      return new Object(); 
     } 
    } 

    @Test 
    public void testThis() { 

    } 
} 

结果:

org.springframework.beans.factory.NoSuchBeanDefinitionException:发现依赖 [类型[SpringTest $项目]无 预选赛豆SpringTest $ Item的集合]:预计至少有1个bean,其中 有资格作为此依赖关系的自动导向候选。依赖 注解:{}

如果我改变从List<Item>Item,工作的事情。

这是设计吗?任何解决方法?我需要提供一个List项目 - 有时是空的,有时候还有项目,具体取决于运行时配置。

我知道,如果我指定类型为Item的bean,自动装配List<Item>的作品。但是,我想要一个类型为List<Item>的豆子(或者如果我不能那样做,请拨打List)。

使用Spring 4.2.4。

+0

Spring的源代码通常非常清晰 - 可能需要查看该异常的堆栈跟踪,在查找合格Bean的位置查找代码,以及查看它的功能。开源的万岁! – slim

+0

使用'@ Qualifier'是否有用? – CollinD

+0

@CollinD - 我刚刚用'@ Qualifier'试过 - 不,它没有帮助。 – slim

回答

8

该片段在Spring 4.3+中可以正常工作。所述documentation状态

这就是说,如4.3,收集/地图和数组类型的可以由Spring @Autowired类型匹配算法匹配 以及[其中 也用于@Bean参数分辨率],只要作为元素 类型信息保存在@Bean返回类型签名或 集合继承层次结构中。在这种情况下,可以使用限定符值 来选择相同类型的集合,如 上一段所述。

预4.3,当弹簧看到

@Bean 
Object foo(List<Item> obj) { 

它试图动态地创建一个List对象,包含在ApplicationContext发现所有的Item豆。您的ApplicationContext不包含任何内容,因此Spring会报告错误。

以下是一些解决方法。这

@Bean 
Object foo() { 
    List<Item> someString = someString(); 
    return new Object(); 
} 

直接使用缓存的bean工厂方法,someString

@Resource(name = "someString") 
private List<Item> items; 
// and access 'items' wherever you need it in the configuration 

作品,因为

如果要表达的名字注解驱动的注入,不 主要使用@Autowired,即使在技术上能够参考 到的bean名称通过@Qualifier值。 而是使用JSR-250 @资源注释,其语义定义为通过其唯一名称来标识特定目标组件,其中声明的类型 与匹配过程无关。 @Autowired具有不同的语义:在按类型选择候选bean后,指定的字符串限定符值将仅在那些 类型选择的候选者中被考虑,例如,将“帐户”限定符 与标有相同限定符标签的bean进行匹配。

+0

你是对的。对我来说,似乎很疯狂,我所尝试过的东西在4.3之前是行不通的--Spring 4.2.6并不是那么古老。 – eis

+0

@eis我猜他们认为很少必须声明一个集合类型的bean,因此从来没有实现它。更有可能宣布一堆'Foo'豆,并且需要将它们一起注入。 –

+0

我发现另一个解决方法是 '@Bean 对象foo(ApplicationContext的CTX){ 列表列表= ctx.getBean( “someString”,List.class); return new Object(); }' - 不漂亮,但至少我仍然可以拥有相同的机制 – eis

相关问题