My question is simple. Which approach is more efficient?
method 1:
@Autowired
private CustomerRepository customerRepo;
method 2:
private final CustomerRepository custormerRepo;
public StudentService(CustomerRepository customerRepo) {
this.customerRepo = customerRepo;
}
As I see the DI in the method2 is more recent. But I wanted to ask you which one should I use?
CodePudding user response:
TL;DR: Method 2 is much more flexible.
Method 1 is an example of field injection and method 2 is an example of construction injection.
Field injection has some drawbacks that constructor injection avoids. Here are some advantages of constructor injection:
Immutability:
You can't do this is plain Java:
@Autowired
private final CustomerRepository customerRepo;
// No constructor that sets "customerRepo".
So, Spring offers constructor injection:
private final CustomerRepository customerRepo;
@Autowired
public StudentService(final CustomerRepository customerRepo) {
this.customerRepo = customerRepo;
}
Immutability is sometimes preferred. One reason is that it helps with thread-safety.
Personally, I follow the rule, "if it can be final, it should be final."
Testing:
You won't need reflection to set the dependencies. Yes, many mocking frameworks handle this for you, but with constructor injection, you have the option to call new
on the constructor.
Nasty NullPointerException
s:
An object is created by calling its constructor, right? We usually want our arguments to be non-null at the time they are passed in. With constructor injection, the Spring IoC container makes sure that all the arguments passed in the constructor are available before passing them into the constructor.
CodePudding user response:
use constructor injection, Spring also recommends it
CodePudding user response:
In your main code, you should use method 2 as field injection (method 1) is not recommended. (see here for reasons)
In your test code, it's okay to use method 1.
CodePudding user response:
In addition to what the other answers have said about immutability, another benefit of constructor injection is to be able to avoid NPE is the field is not initialized. Using autowired, from a test, you’d create the class and then must remember to set the field. Using constructor injection, you can’t not initialize the field. This is more prominent in Kotlin where autowired fields are declared as lateinit var
and throw a runtime exception if used before initialized. But a constructor argument can be declared as not null type which prevents you from even explicitly passing null.