Spring无法为List类型的bean解析@Bean依赖关系?

时间:2017-01-05 16:55:10

标签: java spring

简单的测试类显示我的问题:

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。

1 个答案:

答案 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。