SPRING: CONSTRUCTOR - BASED DEPENDENCY INJECTION Concepts, Java Examples, Configuration and Best Practices Made by Rachit Joshi 1. Introduction Spring is a Java framework that helps developers build applications by managing objects and their relationships. One of its core ideas is Inversion of Control (IoC): rather than having each object create or locate all of its dependencies itself, the Spring container manages object creation and supplies the required collaborators. Dependency injection (DI) is the technique of providing an object with the other objects it needs. Constructor - based dependency injection supplies those dependencies as constructor parameters. Spring's documentation generally recommends constructor injection for required dependencies because it makes components easier to initialize and test. 2. What Is Constructor - Based Dependency Injection? Constructor - based dependency injection is a form of DI in which the Spring container creates a bean by calling its constructor and passing the required dependency objects as arguments. The class declares what it needs, while Spring resolves and supplies the matching beans. For example, a TextEditor may require a SpellChecker. Instead of creating a SpellChecker internally, TextEditor accepts one through its constructor. 3. How It Works 1. A class declares its required collaborators as constructor parameters. 2. The dependencies are registered as Spring beans, for example through component scanning or Java configuration. 3. When Spring creates the dependent bean, it resolves the constructor parameters to suitable beans. 4. The constructor stores or uses those dependencies, leaving the object initialized and ready to work. 4. Simple Java Example The following example uses Spring annotations. In a Spring application with component scanning enabled, both classes can be registered as beans. import org.springframework.stereotype.Component; @Component public class SpellChecker { public void checkSpelling() { System.out.println("Checking spelling..."); } } import org.springframework.stereotype.Component; @Component public class TextEditor { private final SpellChecker spellChecker; public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void editText() { spellChecker.checkSpelling(); System.out.println("Editing text..."); } } Because TextEditor has one constructor, modern Spring versions can use it for injection without requiring @Autowired. The final field also makes the reference unchangeable after construction. 5. Java Configuration Example Beans can also be declared with @Configuration and @Bean methods. This approach is useful when you want explicit control over how objects are created. import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public SpellChecker spellChecker() { return new SpellChecker(); } @Bean public TextEditor textEditor(SpellChecker spellChecker) { return new TextEditor(spellChecker); } } Spring resolves the SpellChecker bean and passes it to the TextEditor constructor. In a real application, avoid registering the same class twice through overlapping configuration approaches unless that is intentional. 6. Constructor Injection with XML Configuration Traditional Spring applications can define beans and constructor references in XML. The exact XML namespace and project setup depend on the application. <beans> <bean id="spellChecker" class="example.SpellChecker" /> <bean id="textEditor" class="example.TextEditor"> <constructor - arg ref="spellChecker" /> </bean> </beans> Here, constructor - arg tells Spring to pass the bean named spellChecker to the TextEditor constructor. Ensure the class names and XML namespaces match the project configuration. 7. Advantages • Required dependencies are explicit in the constructor signature. • Objects can be created in a fully initialized state. • Dependencies can often be stored in final fields. • Unit testing is easier because dependencies can be supplied directly, including mock implementations. • Classes are less coupled to the process of finding or creating their dependencies. 8. Constructor Injection vs. Setter Injection Aspect Constructor injection Setter injection How dependency is supplied As a constructor argument when the object is created. Through a setter method after construction. Best suited for Required dependencies. Optional dependencies or dependencies that may be reconfigured. Initialization Can ensure required collaborators are supplied before the object is used. The object may exist before optional dependencies are assigned. Mutability Supports immutable design when fields are final. Usually allows dependency references to be changed. A practical rule is to use constructors for mandatory dependencies and setters for genuinely optional ones. 9. Important Notes and Common Errors • Missing bean: Spring cannot inject a dependency if no suitable bean is available in the application context. • Multiple candidates: if multiple beans match a constructor parameter, specify which one should be used, for example with @Primary or @Qualifier where appropriate. • Multiple constructors: when a class has multiple constructors, explicitly identify the intended injection constructor when Spring cannot choose unambiguously. • Circular dependencies: two beans that require each other through constructors can create an unresolvable cycle; redesigning the dependency relationship is usually preferable. • Too many parameters: a constructor with many dependencies may indicate that the class has too many responsibilities. 10. Best Practices • Prefer constructor injection for required dependencies. • Use interfaces for dependencies when that improves flexibility and testing. • Keep constructors focused and validate required arguments when appropriate. • Use final fields for dependencies that should not change after construction. • Keep application configuration clear and avoid duplicate bean registrations. • Write unit tests that pass test doubles or mocks through the constructor. 1 1 . Conclusion Constructor - based dependency injection is a clear and testable way to provide required collaborators to Spring - managed objects. By declaring dependencies in constructors, developers make class requirements explicit and help ensure objects are ready for use after creation. For most mandatory dependencies, constructor injection is a strong default; optional dependencies may be better handled with setters or configuration methods.