Constructor versus setter injection
- by Chris
Hi,
I'm currently designing an API where I wish to allow configuration via a variety of methods. One method is via an XML configuration schema and another method is through an API that I wish to play nicely with Spring.
My XML schema parsing code was previously hidden and therefore the only concern was for it to work but now I wish to build a public API and I'm quite concerned about best-practice.
It seems that many favor javabean type PoJo's with default zero parameter constructors and then setter injection. The problem I am trying to tackle is that some setter methods implementations are dependent on other setter methods being called before them in sequence.
I could write anal setters that will tolerate themselves being called in many orders but that will not solve the problem of a user forgetting to set the appropriate setter and therefore the bean being in an incomplete state.
The only solution I can think of is to forget about the objects being
'beans' and enforce the required parameters via constructor injection.
An example of this is in the default setting of the id of a component based on the id of the parent components.
My Interface
public interface IMyIdentityInterface {
public String getId();
/* A null value should create a unique meaningful default */
public void setId(String id);
public IMyIdentityInterface getParent();
public void setParent(IMyIdentityInterface parent);
}
Base Implementation of interface:
public abstract class MyIdentityBaseClass implements IMyIdentityInterface {
private String _id;
private IMyIdentityInterface _parent;
public MyIdentityBaseClass () {}
@Override
public String getId() {
return _id;
}
/**
* If the id is null, then use the id of the parent component
* appended with a lower-cased simple name of the current impl
* class along with a counter suffix to enforce uniqueness
*/
@Override
public void setId(String id) {
if (id == null) {
IMyIdentityInterface parent = getParent();
if (parent == null) {
// this may be the top level component or it may be that
// the user called setId() before setParent(..)
} else {
_id = Helpers.makeIdFromParent(parent,getClass());
}
} else {
_id = id;
}
}
@Override
public IMyIdentityInterface getParent() {
return _parent;
}
@Override
public void setParent(IMyIdentityInterface parent) {
_parent = parent;
}
}
Every component in the framework will have a parent except for the top level component. Using the setter type of injection, then the setters will have different behavior based on the order of the calling of the setters.
In this case, would you agree, that a constructor taking a reference to the parent is better and dropping the parent setter method from the interface entirely? Is it considered bad practice if I wish to be able to configure these components using an IoC container?
Chris