I am working on spring based project where we use constructor injection and configure context using @Configuration
.
Here is the simplified example that shows my problem.
I have bean MyMainBean
that refers to collection of Foo
beans:
public class MyMainBean {
private Collection<Foo> foos;
public MyMainBean(Collection<Foo> foos) {
this.foos = foos;
}
}
Here is the bean 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);
}
}
Here is how configuration class looks like:
@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"));
}
}
When I run this I get exception message:
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: {}
The message is pretty clear, so although it is not what I need I added the following methods to AppConfig
:
@Bean
public Foo foo1() {
System.out.println("foo1");
return new Foo("single1");
}
and similar foo2()
Now the context runs and beans are wired. But although foo1()
, foo2()
and foos()
are called the MyAppBean
receives in its constructor collection that contains 2 elements created by foo1()
and foo2()
.
I want to get foos()
working because in my real code similar method retrieves the list of Foo
dynamically using configuration. I believe that some magic annotations are missing here because I can create list of beans using context.xml
, but I have to use programmatically created context here.
As a workaround I can create FooFactory
bean that will expose method getFoos()
and wire this factory to MyMain
, however this looks ugly. Is there better solution?
Remarks
- Attempts to add
@Qualifier
did not help
- Attempts to work with
@Autowire
and @Resource
instead of constructor injection did not help too.