Spring injects dependencies in constructor without Autowired annotation
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Spring Framework is renowned for its ability to simplify the management of application components and dependencies through its Inversion of Control (IoC) container. A common pattern in Spring applications is to use dependency injection to provide components and their dependencies. One often-used method in Spring is constructor-based injection, which can be performed without explicitly using the @Autowired annotation. In this article, we'll explore how Spring’s IoC container can automatically handle constructor injection, delve into an example, and examine the implications of this approach.
Constructor-Based Dependency Injection in Spring
Constructor-based dependency injection is a technique where dependencies are provided to a class via its constructor. This pattern ensures that a class is instantiated with all its required dependencies, enforcing immutability and promoting testability by leveraging dependency inversion.
Injecting Dependencies without @Autowired
In Spring, constructor-based injection can work without using the @Autowired annotation. By default, when a class has a single constructor, Spring's IoC container will automatically use this constructor to inject dependencies. The @Autowired annotation becomes implicit in this scenario.
How Spring Resolves Constructor Injection
When Spring is initialized and scans for components, it uses reflection to inspect available classes. Upon encountering classes with a single constructor, it automatically resolves the required dependencies by matching them against beans declared in the context. If multiple beans can satisfy a dependency and are not explicitly disambiguated, Spring will raise an exception.
Example
Consider an application with a MessageService and a Client class:
In the above code, the Client component relies on MessageService. The constructor of Client receives the MessageService as a dependency. Since there is only one constructor in the Client class, Spring will autowire MessageService directly without the need for @Autowired.
Benefits of Constructor-Based Injection
- Immutability: Dependencies are set at object instantiation time and cannot change, leading to immutable objects.
- Testability: Constructor injection naturally supports mocking or stubbing of dependencies for unit testing.
- Simplicity: Reduces boilerplate code by avoiding the
@Autowiredannotation in straightforward scenarios.
Handling Multiple Constructors
When a class has more than one constructor, Spring does not automatically know which one to use. In such cases, @Autowired can be used to indicate the preferred constructor:
Key Considerations
- Single vs Multiple Constructors: Automatic injection without
@Autowiredonly works for classes with a single constructor. - Required Dependencies: Ensure that the required beans are available in the application context, or else
NoSuchBeanDefinitionExceptionwill be raised. - Clearer Intent: Leveraging constructor injection clarifies the mandatory dependencies of a class.
- Circular Dependencies: Constructor injection cannot be used to create circular references between beans. Setter injection or field injection might be necessary in such cases.
Table Summary
| Aspect | Description |
| Automatic Wiring | Works with a single constructor; no need for @Autowired. |
| Immutability | Promotes immutable objects by setting dependencies at construction time. |
| Enhanced Testability | Facilitates unit testing by allowing easy mocking or stubbing of dependencies. |
| Multiple Constructors | @Autowired or other methods must specify the constructor to use when more than one constructor is present. |
| Contextual Requirements | All constructor dependencies must be present as beans in the Spring context. |
| No Circular Dependencies | Not suitable for circular dependencies—consider using other injection methods in such cases. |
Additional Considerations
- Configuration: Ensure all component classes are appropriately annotated or defined in configuration classes for Spring to discover them.
- Migration: Existing projects using different wiring configurations (XML, setter injection) can incrementally migrate to constructor injection for components where feasible.
In conclusion, Spring's capability to inject dependencies via a class's constructor, even without @Autowired, simplifies configuration and enhances the robustness of applications. This design enforces constructor injection, favoring component immutability and laying a strong foundation for modular, maintainable codebases. Understanding the nuances of this approach can be advantageous for developers aiming to leverage Spring's IoC container effectively.

