I'm trying to find the most elegant and Spring way to create an (unlimited) of Spring managed beans.
One of the questions is why I'd need to do it. The most common use-case I have is when using Vaadin I have to create a list of layout depending on a collection fetched from database. Based on that I'll create a list of layouts that might require access to Spring services.
There are 2 methods that I'm using at the moment:
//Spring ApplicationContext
@Component
public class MainLayout {
@Autowired ApplicationContext ctx;
public void init() {
items.forEach(i -> this.add(ctx.getBean(ChildLayout.class, i));
}
}
//This works well if ChildLayout has autowired dependencies and no arguments
@Component
@Scope("prototype")
public class ChildLayout {
@Autowired ServiceA serviceA;
@Autowired ServiceB serviceB;
public ChildLayout(MyDTO item) {
//IDE Interpreter will complain that MyDTO is not a Spring Component (because it's not)
...
}
}
Then I figured out that I could create use a factory pattern and move to a Constructor Based bean injection as it's recommended.
@Component
public class ChildLayoutFactory {
private final ServiceA serviceA;
private final ServiceB serviceB;
public ChildLayoutFactory(ServiceA a, Service b) {...}
public ChildLayout create(MyDTO dto) {
return new ChildLayout(a, b, dto)
}
}
public class ChildLayout {
ServiceA serviceA;
ServiceB serviceB;
public ChildLayout(ServiceA a, ServiceB b, MyDTO item) {
this.serviceA = a;
this.serviceB = b;
...
}
}
@Component
public class MainLayout {
@Autowired ChildLayoutFactory childLayoutFactory; //Or constructor based
public void init() {
items.forEach(i -> this.add(childLayoutFactory.create(i));
}
}
Both methods work fine. The problem with the second is that I need an extra class and that if I have also some extra dependency that I need to create on the fly I'll need to pass the dependency on the constructors upstream.
Is there any way what I could combine the advantages of both? Is it recommended to do it as shown?