Issue
Suppose I have interface foo and bar, then have multiple classes that implements both of them:
public interface InterfaceFoo{
int getFoo()
}
public interface InterfaceBar{
int getBar()
}
public class FooBarOne implements InterfaceFoo, InterfaceBar{
public int getFoo() { ... }
public int getBar() { ... }
}
public class FooBarTwo implements InterfaceFoo, InterfaceBar{
public int getFoo() { ... }
public int getBar() { ... }
}
Then I create beans for both of these classes:
@Configuration
@ComponentScan
public class Config {
@Bean
fooBarOne getFooBarOne() { return new FooBarOne(); }
@Bean
fooBarTwo getFooBarTwo() { return new FooBarTwo();}
}
Finally another bean which @Autowries in a list of all implementations of foo
@Configuration
@ComponentScan
public class FooConfig {
@Bean
@Autowired
public List<InterfaceFoo> fooFetcher(List<<InterfaceFoo>> listFoos) {
return listFoos;
}
}
My question is, how does Spring identify/autowire beans when they have multiple implementations of an interface? The above pseudo code seems to work, however, if I change the return type of the bean from the concrete class to an ibar, it is not picked up by the autowire:
@Configuration
@ComponentScan
public class Config {
@Bean
InterfaceBar getFooBarOne() { return new FooBarOne(); }
@Bean
InterfaceBar getFooBarTwo() { return new FooBarOne(); }
}
From the example above, spring does not pick these beans up when autowiring for implementations of ifoo. Switching the return type to ifoo works, which implies to me that spring looks at the return type of the bean rather than that of the returned object? Even though fooBarOne and fooBarTwo both implement foo and bar, do I need to return either the concrete class or interface ifoo if I want the autowire for List to pick it up?
Solution
Spring's default autowire mode is by type, so it makes sense that if you create two beans of type iBar
, they will not be autowired as iFoo
, even though the concrete classes are also instances of iFoo
. Spring does not know about all of the interfaces that a class implements, it only knows of the type of beans that were created in its context.
When you attempt to autowire List<<iFoo>>
, Spring will look in its context for all the beans of type iFoo
to inject, which you have none.
Also, please read up on the Java naming conventions, you probably want your interfaces to just be Foo
and Bar
https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html
Answered By - lane.maxwell
Answer Checked By - David Marino (JavaFixing Volunteer)