Reputation: 86905
I'm using CDI in Vaadin context, but that should not matter for my question: Is it in general better to inject objects inside the constructor, or directly as a member variable? Especially if these objects have to be further configured for the component to work.
The following shows two different CDI possibilities:
@UIScoped
public class MyMenuBar extends CustomComponent {
@Inject @New private Label label;
@Inject @New private MenuBar menuBar;
@PostConstruct
private void init() {
//set label text, define menu entries
setCompositionRoot(menuBar);
}
}
@UIScoped
public class MyMenuBar extends CustomComponent {
private Label label;
private MenuBar menuBar;
@Inject
public MyMenuBar(@New Label label, @New MenuBar menuBar) {
//set label text, define menu entries
setCompositionRoot(menuBar);
}
}
Is there a best practice? Why should one prefer the one option over the other? Or is it just a matter of personal choice?
Upvotes: 5
Views: 3731
Reputation: 27536
Always use @PostConstruct
when you work with injected resources(CDI and EJB beans for instance) because only then you can be sure that they really have been already injected into the bean (this is provided by the container). So that's the reason why you shouldn't rely on constructor when it comes to injected resources (they might get injected but you can't be sure).
However, constructor initialization can still be useful if you deal with non-injected resources, so you can call some methods or init variables, it's more matter of taste in this case. But you can never make mistake by using @PostConstruct
all the time.
Upvotes: 4
Reputation: 40318
The constructor is ONLY for object construction stuff; i.e. NEVER CALL BUSINESS LOGIC FROM THE CONSTRUCTOR. Allways use @PostConstruct
for business initialization logic. See my answer to this for a more detailed explanation.
In short the constructor may be called by the system in "unexpected" ways.
Additionally, in @PostConstruct
you are guaranteed to have all dependencies (event fields) injected.
Upvotes: 6