Spring: get all Beans of certain interface AND type
JavaSpringSpring BootAutowiredJava Problem Overview
In my Spring Boot application, suppose I have interface in Java:
public interface MyFilter<E extends SomeDataInterface>
(a good example is Spring's public interface ApplicationListener< E extends ApplicationEvent > )
and I have couple of implementations like:
@Component
public class DesignatedFilter1 implements MyFilter<SpecificDataInterface>{...}
@Component
public class DesignatedFilter2 implements MyFilter<SpecificDataInterface>{...}
@Component
public class DesignatedFilter3 implements MyFilter<AnotherSpecificDataInterface>{...}
Then, in some object I am interested to utilize all filters that implement MyFilter< SpecificDataInterface > but NOT MyFilter< AnotherSpecificDataInterface >
What would be the syntax for this?
Java Solutions
Solution 1 - Java
The following will inject every MyFilter instance that has a type that extends SpecificDataInterface as generic argument into the List.
@Autowired
private List<MyFilter<? extends SpecificDataInterface>> list;
Solution 2 - Java
You can simply use
@Autowired
private List<MyFilter<SpecificDataInterface>> filters;
Edit 7/28/2020:
As Field injection is not recommended anymore Constructor injection should be used instead of field injection
With constructor injection:
class MyComponent {
private final List<MyFilter<SpecificDataInterface>> filters;
public MyComponent(List<MyFilter<SpecificDataInterface>> filters) {
this.filters = filters;
}
...
}
Solution 3 - Java
In case you want a Map<String, MyFilter>
, where the key
(String
) represents the bean name:
private final Map<String, MyFilter> services;
public Foo(Map<String, MyFilter> services) {
this.services = services;
}
which is the recommended
alternative to:
@Autowired
private Map<String, MyFilter> services;
Solution 4 - Java
In case you want a map, below code will work. The key is your defined method
private Map<String, MyFilter> factory = new HashMap<>();
@Autowired
public ReportFactory(ListableBeanFactory beanFactory) {
Collection<MyFilter> interfaces = beanFactory.getBeansOfType(MyFilter.class).values();
interfaces.forEach(filter -> factory.put(filter.getId(), filter));
}