简单的测试类显示我的问题:
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 $ Item]类型的限定bean [SpringTest $ Item的集合]:预计至少有1个bean 有资格作为此依赖项的autowire候选者。依赖 注释:{}
如果我从List<Item>
更改为Item
,事情就会奏效。
这是设计的吗?任何解决方法?我需要提供List
个项目 - 有时是空的,有时还有项目,具体取决于运行时配置。
我知道如果我指定类型为Item的bean,则自动装配List<Item>
有效。但是,我想要一个类型为List<Item>
的bean(或者我不能拥有List
)。
使用Spring 4.2.4。
答案 0 :(得分:8)
该片段在Spring 4.3+中可以正常使用。 documentation州
也就是说,从4.3开始,可以匹配集合/映射和数组类型 通过Spring的
@Autowired
类型匹配算法以及 [which 也用于@Bean
参数解析] ,只要元素 类型信息保存在@Bean
返回类型签名或 集合继承层次结构。在这种情况下,限定符值可以 用于在相同类型的集合中进行选择,如中所述 前一段。
Pre 4.3,当Spring看到
@Bean
Object foo(List<Item> obj) {
它会尝试动态创建一个List
对象,其中包含Item
中找到的所有ApplicationContext
个bean。您的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,即使技术上能够引用 通过@Qualifier值获取bean名称。 而是使用JSR-250 @Resource注释,在语义上定义为标识a 特定目标组件的唯一名称,具有声明的类型 与匹配过程无关。 @Autowired相当 不同的语义:按类型选择候选bean后, 指定的字符串限定符值将被考虑在那些内 仅类型选择的候选者,例如,匹配&#34;帐户&#34;预选赛 针对标有相同限定符标签的bean。