Why is @Autowired annotation not recommended ?
In this post, I will explain why Autowired annotation is not recommended. I will clarify this question as simply as possible and through examples.
I hope you can answer very well when you come across it :)
As you know, Autowired annotation is used to inject dependencies. You can find a usage example below.
At this point, let’s talk about the dependency injection technique first. Then let’s talk about how it is implemented in the Spring Framework. Next, let’s see the reasons why Autowired annotation, which is a setter injection method, is not recommended.
Spring IOC Container
Spring Framework adopts Program to Interface approach. In this approach, dependencies between classes are provided through interfaces and abstract classes.
IOC(Inversion of Control) is a principle that provides modularity. It takes control from the developer and hands it over to another actor, such as the framework. When we hand over control to the framework, we provide loosely coupling. That is, we minimize dependencies when creating an object.
Now let’s talk about Spring Framework…
As developers we are responsible for creating java objects. This responsibility is passed to Spring IOC Container. Spring IOC Container, also called Application context, is responsible for instantiating java objects known as beans to be created with appropriate parameters and configurations when needed.
The object doesn’t know the concrete classes to which the dependencies are provided.
There are many ways to implement the IOC as you will see in the image below. Dependency injection is one of them.
Dependency Injection
It is a technique in software engineering where the dependencies of another object are provided through an object.
Dependency injection is implemented with 3 different methods.
- Constructor Injection (recommended method)
- Setter Injection (Property Injection)
- Method Injection
The subject of the article and the recommended method is constructor injection. You can find a usage example below.
Why Constructor Injection ?
- Testability — Prevents NullPointer Exception. In testing, it’s easy to pass mock objects to the constructor.
If we had used Autowired, we would have been getting the following error in the test. Therefore, it is not recommended to use Autowired.
- Safety — Forces Spring to provide mandatory dependencies. We make sure that the created objects are valid after construction.
- Readability — Dependencies passed as parameters to the constructor are mandatory. Dependencies provided by the Property or setter injection method are optional.
Finally, I leave it for those who want to read the Spring team’s explanation on this subject.
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; however, constructor injection with programmatic validation of arguments is preferable.
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.
I hope it was useful for you. You can access the source codes from this repo.
Keep coding ! 🚀