I have an interface
public interface Abstraction {
void execute();
}
I have built a composite implementation and want to registered this object as the bean, @Named
@Named
public class Composite implements Abstraction {
private List<Abstraction> list;
@Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
How do I set it up so that the set of implementations to the abstraction gets injected properly into the Composite above? I will be having another object that takes the abstraction as a dependency and I want it to receive the @Named
Composite above with the 2 Implementations below injected into the ctor.
public class Implementation1 implements Abstraction {
public void execute() { }
}
public class Implementation2 implements Abstraction {
public void execute() { }
}
If you create a bean for each of your implementations, your example will work out of the box. For example, annotate your implementations with @Named
or @Component
and mark them for scanning (component scan their package)
@Configuration
@ComponentScan
public class StackOverflow {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StackOverflow.class);
System.out.println(ctx.getBean(Composite.class).list);
}
}
interface Abstraction {
void execute();
}
@Named
class Composite implements Abstraction {
List<Abstraction> list;
@Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
@Named
class Implementation1 implements Abstraction {
public void execute() {
}
}
@Named
class Implementation2 implements Abstraction {
public void execute() {
}
}
The Composite
's list will contain both implementations.
Alternatively, since you only have two implementations, you could name their beans and inject them separately. For example
@Component("one")
class Implementation1 implements Abstraction {
public void execute() {
}
}
@Component("two")
class Implementation2 implements Abstraction {
public void execute() {
}
}
and inject them in the Composite
List<Abstraction> list = new ArrayList<>(2);
@Inject
public Composite(@Qualifier("one") Abstraction one, @Qualifier("two") Abstraction two) {
list.add(one);
list.add(two);
}
I suggest this solution just because the order of initialization of Abstraction
beans might mess up your context initialization. For example if Implementation1
somehow depended on the initialization of Composite
, the context would complain. This is rare and you can control it in other ways. Still, being explicit about the beans might be clearer in this case.