2014-05-07 98 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")); 
    } 
}