2014-05-07 126 views
0

我正在基於spring的項目中使用構造函數注入並使用@Configuration配置上下文。使用註釋向構造函數注入bean的集合

下面是顯示我的問題的簡單示例。

我有豆MyMainBean是指Foo豆集:

public class MyMainBean { 
    private Collection<Foo> foos; 
    public MyMainBean(Collection<Foo> foos) { 
      this.foos = foos; 
    } 
} 

這裏是豆Foo

public class Foo { 
    private final String name; 
    public Foo(String name) { 
      this.name = name; 
    } 
    public void foo(String arg) { 
      System.out.println("foo (" + name + "): " + arg); 
    } 
} 

下面是配置類的樣子:

@Configuration 
public class AppConfig { 
    @Bean 
    public MyMainBean myMain(Collection<Foo> foos) { 
     return new MyMainBean(foos); 
    } 

    @Bean 
    public Collection<Foo> foos() { 
     System.out.println("foos"); 
     return Arrays.asList(new Foo("colletion1"), new Foo("colletion2")); 
    } 
} 

當我運行這個時,我得到了excep重刑消息:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.hello.impl.Foo] found for dependency [collection of com.hello.impl.Foo]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 

的信息是很清楚,所以雖然它不是什麼,我需要我增加了以下方法AppConfig

@Bean 
public Foo foo1() { 
    System.out.println("foo1"); 
    return new Foo("single1"); 
} 

和類似foo2()

現在的上下文中運行和豆類有線。但是,儘管foo1(),foo2()foos()被稱爲MyAppBean在其構造函數集合中收到,其中包含由foo1()foo2()創建的2個元素。

我想要foos()工作,因爲在我的真實代碼中,類似的方法使用配置動態檢索Foo的列表。我相信一些魔法註釋在這裏是不存在的,因爲我可以使用context.xml創建bean列表,但是我必須在這裏使用程序創建的上下文。

作爲一種解決方法,我可以創建FooFactory bean,這將暴露方法getFoos()並將此工廠連接到MyMain,但是這看起來很醜。有更好的解決方案嗎?

備註

  1. 嘗試添加@Qualifier沒有幫助
  2. 試圖與@Autowire@Resource工作,而不是構造函數注入並沒有幫助過。

回答

1

由於兩個@Bean在同一AppConfig聲明就可以解決像您的問題:

@Bean 
public MyMainBean myMain() { 
    return new MyMainBean(foos()); 
} 

在不同@Configuration類的情況下,@Resource就派上用場了:

@Resource(name="foos") 
private Collection<Foo> foos; 

的即使使用@Qualifier@Autowire也無法幫助解決此問題。

+0

謝謝,阿爾喬姆。如此明顯而優雅......不幸的是,使用@Resource(name =「foos」)的建議目前還不適用於我,但第一個解決方案已經足夠好了。 – AlexR

+1

爲了記錄,注入集合是Spring框架中的一個特例。當你詢問'Collection '時,Spring試圖找到'Foo'類型的所有bean並將它們收集到所需的集合類型中。這就是爲什麼你的foo集合bean被忽略。 –

0

有點晚了,但我們在這裏:

@Configuration 
public class AppConfig { 

    // Answer 1 : Inject the "foos" collection bean using @Value instead of @Qualifier 
    @Bean 
    public MyMainBean myMain1(@Value("#{foos}") Collection<Foo> foos) { 
     return new MyMainBean(foos); 
    } 

    // Answer 2 : call directly foos() since @Configuration bean is proxified, 
    // "foos" collection bean will only be called and instanciated once (at first call) 
    @Bean 
    public MyMainBean myMain2() { 
     return new MyMainBean(foos()); 
    } 

    @Bean 
    public Collection<Foo> foos() { 
     System.out.println("foos"); 
     return Arrays.asList(new Foo("colletion1"), new Foo("colletion2")); 
    } 
}