I am learning Spring using Spring Recipes. As of now I understood that we can inject dependencies using Setter Injection or Injecting via constructor. My question is, in real world applications what method is used more often and why? I know its a subjective question but I cant think of a better place than this site to get perfect insights. Thanks again.
5 Answers
Constructor injection is preferable over setter injection because it clearly defines what dependencies are needed, and forces you to provide them before you can create an instance of the class. With setter injection, the caller has to figure out what dependencies are needed, and can lead to situations where the caller fails to inject all the necessary dependencies.
However, there are cases where you'll need to use setter injection, such as dealing with objects that only have a default constructor, or setting dependencies where there might be a bi-directional relationship.
When in doubt, try to use constructor injection, and only fall back to setters when needed.
1 Comment
final if they're constructor injected.Constructor injection is considered better than setter injection because of many reasons since constructor injection ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state. Please see this post for an example: http://www.redcode.nl/blog/2010/09/setter-vs-constructor-injection/
Comments
The other answers are already very clean on the fact, that Constructor injection is more save, in terms of forget to set a field. -- You can just not create the instance without the field. So one advice from this statements could be: use constructor injection for mandatory fields and setter or field injection for optional fields.
And Constructor Injection has two other impacts:
- the fields can be
final- (I like final fields, because the make understanding easier) - you can not build circles of classes. (A.b and B.a) - Spring can not instantiate this construction. (*From a architetural point of view, I think this is a pro of constructor injection, not a con)
But on the other hand, if you use constructor injection you have to write a more code than necessary.
public class FieldInjection {
@Ressource //the same like @Autowired(required=true)
private MyService myService;
}
is much shorter than:
public class MethodInjection {
private final MyService myService;
public MethodInjection(final MyService myService) {
assert(myService != null);
this.myService = myService;
}
}
The autors of the other answers will hate me for that statement.
I personally believe that when you have a Class, that is only used as a Spring Bean (but not without Spring) then you can use field Injection without that safety doubt! - Because Spring will only put the Bean in its lifecycle if it can set all fields annotated by @Ressource or @Autowired(required=true). Because of this I prefer field injection because it makes my faster (less to write and less to read). And for all initialialization stuff, I use @PostConstruct. (Of course you can not use the fields in the constructor. And you can not really mix them both.) - That ties my Application much stronger to an IOC container than constructor injetion, but this is not a problem for my usecase. - May you have a look at EJB 3.1 standard, they do not have constructor injection at all.
Comments
There are pros and cons to each way. I would argue that constructor based dependency injection is less error prone, because you are imposing certain rules and telling your class which dependencies its methods needs. More importantly, constructor injection enforces the order of initialization and prevents circular dependencies. With setter injection it is not clear in which order things need to be instantiated and when the wiring is done.
On the other hand, there are reasons why setter injection wins. Unit testing is always easier if constructors are simple and do less, or do nothing at all. Besides, not all methods of a class require the same dependencies. If you use the Spring container to inject your dependencies, then you don’t always have to worry about this because the Spring container will automatically call your setters for you if you configure it correctly.