I couldn't find any reasonable answer here on SO so I hope it's not a duplicate. So why should I prefer setter or constructor injection over simple
#Inject
MyBean bean;
I get the usage of the constructor injection if you need to do something with injected bean during your class initialization like
public void MyBean(#Inject OtherBean bean) {
doSomeInit(bean);
//I don't need to use #PostConstruct now
}
but still, it's almost the same like #PostConstruct method and I don't get setter injection at all, isn't it just a relic after Spring and other DI frameworks?
Constructor and property injection gives you the option to initialize the object even in a non CDI environment easily, e.g a unit test.
In a non-CDI environment you can still simply use the object by just passing the constructor arg.
OtherBean b = ....;
new MyBean(b);
If you just use field injection you usually must use reflection to access the field, because fields are usually private.
If you use property injection you can also write code in the setter. E.g. validation code or you clear internal caches that hold values which are derived from the property that the setter modifies. What you want to do depends on your implementation needs.
Setter vs constructor injection
In object-oriented programming an object must be in a valid state after construction and every method invocation changes the state to another valid state.
For setter injection this means that you might require a more complex state handling, because an object should be in a valid state after construction, even if the setter has not been invoked yet. Thus the object must be in a valid state even if the property is not set. E.g. by using a default value or a null object.
If you have a dependency between the object's existence and the property, the property should either be a constructor argument. This will also make the code more clean, because if you use a constructor parameter you document that the dependency is necessary.
So instead of writing a class like this
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public Customer findById(String id){
checkDataSource();
Connection con = dataSource.getConnection();
...
return customer;
}
private void checkDataSource(){
if(this.dataSource == null){
throw new IllegalStateException("dataSource is not set");
}
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
}
you should either use constructor injection
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public CustomerDaoImpl(DataSource dataSource){
if(dataSource == null){
throw new IllegalArgumentException("Parameter dataSource must not be null");
}
this.dataSource = dataSource;
}
public Customer findById(String id) {
Customer customer = null;
// We can be sure that the dataSource is not null
Connection con = dataSource.getConnection();
...
return customer;
}
}
My conclusion
Use properties for every optional dependency.
Use constructor args for every mandatory dependency.
PS: My blog The difference between pojos and java beans explains my conclusion in more detail.
EDIT
Spring also suggests to use constructor injection as I found in the spring documentation, section Setter-based Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Constructor injection is also a better way when you think about unit tests, because it is easier to call the constructor instead of setting private (#Autowired) fields.
When using CDI, there is no reason whatsoever to use constructor or setter injection. As noted in the question, you add a #PostConstruct method for what would otherwise be done in a constructor.
Others may say that you need to use Reflection to inject fields in unit tests, but that is not the case; mocking libraries and other testing tools do that for you.
Finally, constructor injection allows fields to be final, but this isn't really a disadvantage of #Inject-annotated fields (which can't be final). The presence of the annotation, combined with the absence of any code explicitly setting the field, should make it clear it is to be set by the container (or testing tool) only. In practice, no one will be re-assigning an injected field.
Constructor and setter injection made sense in the past, when developers usually had to manually instantiate and inject dependencies into a tested object. Nowadays, technology has evolved and field injection is a much better option.
Accepted answer is great, however it doesn't give credit to the main advantage of constructor injection - class immutability, which helps to achieve thread-safety, state safety, and better readability on the classes.
Consider you have class with dependencies and all of those dependencies are provided as constructor arguments, then you can know that the object will never exist in a state where dependencies are invalid. There is no need for setters for those dependencies (as long as they are private), so the object is instantiated to a full state or is not instantiated at all.
An immutable object is much more likely to well behave in an multithreaded application. Although the class still needs to be made internally thread-safe, you don't have to worry about external clients coordinating access to the object.
Of course this can be usefull only in certain scenarios. Setter injection is great for partial depencdency, where for example we have 3 properties in a class and 3 arg constructor and setters methods. In such case, if you want to pass information for only one property, it is possible by setter method only. Very useful for testing purposes.
Related
In my Spring boot app i'm creating a Factory for creating different objects with the same interface and dependency like below.
#Component
public class FarmFactory {
#Autowired
private FarmRepo farmRepo;
public IFarm create(FarmType type) {
if (type == type.APPLE) {
return new AppleFarm(farmRepo);
} else if (type == type.ANIMAL) {
return new AnimalFarm(farmRepo);
} else {
return new EmptyFarm(farmRepo);
}
}
}
I was wondering if it was better to limit the scope the FarmRepo dependency by instead injecting it into each subclass of farm (apple, animal, empty). Or if it was better to keep a single dependency in a higher scope of the Factory.
Alternatively the dependency FarmRepo could be passed into the create method with the type, but not sure what the rule of thumb is for dependency scope.
According to my experience, a good design can reduce if-else as much as possible. So I prefer to injecting it into each subclass in your case. Thus in future, you have more flexibility if the dependency also have subclass as well.
I suggest to create named beans of your real implementations (AppleFarm, AnimalFarm ..) and inject the FarmRepo. With you factory your real implementations won't be managed by Spring (no beans).
#Component("appleFarm")
#RequiredArgsConstructor <- this is a Lombok feature check it out
public class AppleFarm implements Farm {
private final FarmRepo repo;
...
}
I assume your IFarm implementations are model classes. It is not a good practise to have a repository inside a model. You should consider to move the creation of different IFarm implementations to the FarmRepo.
If IFarm implementations are some sort of service classes that governs business logic then you should let spring handle it injecting the FarmRepo instance to them. In that case you better consider having an abstract class rather than using IFarm, because FarmRepo is a common dependency among them.
There is nothing wrong in employing a simple factory method to instantiate the required runtime type, if that's required, it needs to be done somewhere, it helps you gain a valid design in terms of OCP (open close principle) preventing you to change bahaviour depending on type parameter, rather you make use of polymorphism.
I have created Spring MVC application that has 3 user types. I've created separate controllers for each of them. Now in each of them, I have to inject service classes so I have done it like this:
#Controller
#RequestMapping("teacher")
public class TeacherController {
#Autowired
private StudentService studentService;
#Autowired
private GradeService gradeService;
#Autowired
private SubjectService subjectService;
#Autowired
private StudentGroupService studentGroupService;
#Autowired
private NewsService newsService;
#GetMapping("/index")
public String indexPage(Model theModel) {
List<News> tempNewsList = newsService.getNews();
theModel.addAttribute("theNewList", tempNewsList);
return "teacher/index";
}
This code is using field injection. Which is, as I now learned, a solution that should be avoided and replaced with constructor injection. So I've Autowired a constructor with all of these fields like this:
#Autowired
public TeacherController(StudentService studentService, GradeService gradeService, SubjectService subjectService, StudentGroupService studentGroupService, NewsService newsService) {
this.studentService = studentService;
this.gradeService = gradeService;
this.subjectService = subjectService;
this.studentGroupService = studentGroupService;
this.newsService = newsService;
}
Is this a good solution, creating such verbose constructor in such simple code? And what if I had even more services in my code? Is this even acceptable or in this case should I refactor my code, e.g. delegate services to other services or create more controllers?
You answered this well yourself! Spring addresses exactly this concern in the docs here in the box titled Constructor-based or setter-based DI?:
The Spring team generally advocates constructor injection, as it lets
you implement application components as immutable objects and ensures
that required dependencies are not null. Furthermore,
constructor-injected components are always returned to the client
(calling) code in a fully initialized state. As a side note, a large
number of constructor arguments is a bad code smell, implying that the
class likely has too many responsibilities and should be refactored to
better address proper separation of concerns.
That is, you should ideally refactor. Used SOLID principles and think "what is the one job of the class I'm creating?".
In conclution, according to the documentation if exist many DI you can evaluate every one and try to use set based and/or contructor based. The documentations eplain which one to use below:
Constructor-based or setter-based DI?
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the #Required annotation on a setter method can be used to make the property be a required dependency.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.
Hi I have a very simple dagger questions for android.
class Fooz {
#Inject Foo1 mFoo1;
public Fooz() {
....
}
}
class Fooz {
private Foo1 mFoo1;
#Inject public Fooz(Foo1 foo1) {
mFoo1 = foo1;
}
}
How are the two classes identical?
The first one injects Foo1 field directly while the second one assignes mFoo1 in the constructor.
For the second one, does Foo1 get injected from object graph as soon as Fooz is created and added to object graph?
If they are different, why so?
Thanks!
Constructor injection gives you more control over the object instantiation since using field injections means to restrict your class creation to reflection and rely on support to these particular injection annotations. Besides that, having the dependencies clearly on the constructor let the code easier to maintain and to test.
As far as I know, there is no difference regarding the way it is held on the dagger graph but a constructor call is always faster than injected fields.
In my opinion, we should use property only when we do not have control over the object creation, as in Activities and Fragments, per example.
These classes will behave the same when Fooz will be Injected using dependency injection. However they will behave differently when constructed using Constructor's you defined.
Example 1. Calling new Fooz() will result in mFoo1 being null.
Example 2. Calling new Fooz(foo1) will result in mFoo1 being initialized to foo1.
The preferred (personal opinion) way is to use dependency injection annotation on constructor, because it will avoid null pointer exceptions, as explained when comparing example 1 and example 2. What is more such constructor gives more flexibility when testing your classes as you can provide mocks, much easier.
These is sonarqube rule with better description, explaining what I mentioned https://sonarcloud.io/coding_rules?open=squid%3AS3306&rule_key=squid%3AS3306 .
I am new to Guice. Is constructor injection preferred or field injection preferred?
Field injection appears to be quick and simple but testing would be a challenge as constructor is missing.
Thanks.
Use constructor injection
On their Minimize mutability wiki page, the Guice team says:
Minimize mutability
Wherever possible, use constructor injection to create immutable objects. Immutable objects are simple, shareable, and can be composed. Follow this pattern to define your injectable types:
[...]
Injecting methods and fields
Constructor injection has some limitations:
Injected constructors may not be optional.
It cannot be used unless objects are created by Guice. This is a dealbreaker for certain frameworks.
Subclasses must call super() with all dependencies. This makes constructor injection cumbersome, especially as the injected base class changes.
Method injection is most useful when you need to initialize an instance that is not constructed by Guice. Extensions like AssistedInject and Multibinder use method injection to initialize bound objects.
Field injection has the most compact syntax, so it shows up frequently on slides and in examples. It is neither encapsulated nor testable. Never inject final fields; the JVM doesn't guarantee that the injected value will be visible to all threads.
Would like to point out some differences so you can decide for yourself:
With constructor injection you can use the final modifier. Can't do that with field injection. Advantages of final members are off-topic and you can read up on that.
Writing test cases with constructor injection is easy (like you already mentioned)
With constructor injection all dependencies are mandatory. In order to declare a class you would need to know all its required dependencies.
With field injection, you will hide your dependencies for the class instead of making them explicit.
Above are just a few points to think about. I personally prefer Constructor Injection because of ease of testing and final support.
Both the types are fine. But you need to know when and where you need to use constructor injection.
Advantages of Constructor injection are,
It Provides Immutability (If used Properly)
In Constructor Injection you can use something like this.
public class MemberResource {
private final IMemberService memberService;
#Inject
public MemberResource(IMemberService memberService) {
this.memberService = memberService;
}
}
Unit testing becomes easier.
Advantage of Field injection is less coding.
public class Widget {
#Inject
Fizz fizz;
public Widget(Fizz fizz) {
super();
setFizz(fizz);
}
public void setFizz(Fizz fizz) {
this.fizz = fizz;
}
}
Is this a Guice anti-pattern?!?!
If I say "fizz will be injected (via #Inject)", but then I allow a constructor and setter to accept a fizz, is this unnecessarily-redundant? Could it cause a conflict with Guice's injector?
I guess I'm confused as to:
When you should annotate a property with #Inject, vs.
When you should "inject" the property yourself via constructor/getter
Any thoughts? Thanks in advance!
Why not use something like this (i.e. use constructor injection) ?
public class Widget {
private Fizz fizz;
#Inject
public Widget(Fizz fizz) {
super();
this.fizz = fizz;
}
}
See also http://code.google.com/p/google-guice/wiki/Injections
You should use Constructor Injection for dependencies that are REQUIRED.
Use Property Injection when the dependency is OPTIONAL.
I would definitely say this is a problem, not because Guice can't do it, but because your code has a bug. Guice will try to invoke the default no-arg constructor (which doesn't exist) and fail.
But even if you added the no-arg constructor, this is still an anti-pattern. I've used DI frameworks for a while and never encountered a need to do field injection. I'm sure there's a use case for it, otherwise the Guice guys wouldn't have included it, but it makes your code impossible to test without special code, either bytecode manipulation or reflection.
Constructor injection is generally best for a number of reasons. It makes it clear to any caller exactly what your dependencies are, it allows you to initialze all your class's invariants at the same time (avoiding a partially-initialized class), and it's the only DI flavor that lets you create immutable objects, which are thread-safe and reduce program complexity.
My only use cases for method injection are when I don't want to require a subclass to declare the parent's dependencies, or when I want an "optional" dependency, but these are rare.