So since I've been using Spring, if I were to write a service that had dependencies I would do the following:
@Component
public class SomeService {
@Autowired private SomeOtherService someOtherService;
}
I have now run across code that uses another convention to achieve the same goal
@Component
public class SomeService {
private final SomeOtherService someOtherService;
@Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Both of these methods will work, I understand that. But is there some advantage to using option B? To me, it creates more code in the class and unit test. (Having to write constructor and not being able to use @InjectMocks)
Is there something I'm missing? Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Autowired
constructors provides a hook to add custom code before registering it in the spring container. SupposeSomeService
class extends another class namedSuperSomeService
and it has some constructor which takes a name as its argument. In this case,Autowired
constructor works fine. Also, if you have some other members to be initialized, you can do it in the constructor before returning the instance to spring container.I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like
new SomeService()
), which is NOT good as you needSomeOtherService
object (as a dependency) for yourSomeService
.Option(B) is preferred approach as it does NOT allow to create
SomeService
object without actually resolving theSomeOtherService
dependency.Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.