🎉 Special Offer !    Code: GET300OFF    Flat ₹300 OFF on every Java Course
Grab Deal 🚀

Constructor Injection in Spring


Introduction

  • Constructor Injection is a form of Dependency Injection where an object’s dependencies are provided at the time of its creation through its Constructor.

  • In Constructor Injection, dependencies are passed as parameters to the class’s constructor, making them explicit and mandatory for creating the instance.
  • This approach ensures that all essential dependencies are provided when creating an object; if a dependency is not supplied, the object cannot be instantiated, clarifying the requirements for the class to function properly.

  • Now we will create 2 programs for Constructor Injection
    1. Using Java Configurations
    2. Using XML Configurations

    Program 1
    First we will create program using Java Configurations. In this example we will take 2 classes i.e. Engine & Car. The Car class depends on the Engine class and The Engine is injected via the Car constructor.
    Engine.java
    package in.sp.beans;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Engine 
    {
        public void start() 
        {
            System.out.println("Engine started...");
        }
    }
    Car.java
    package in.sp.beans;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Car 
    {
        private Engine engine;
    
        // Dependency Injection via Constructor
        public Car(Engine engine) 
        {
            this.engine = engine;
        }
    
        public void drive() 
        {
            engine.start();
            System.out.println("Car is running...");
        }
    }
    NOTE : Its good practice to use final keyword for fields (private final Engine engine;) that should not change after initialization, especially for dependencies injected via constructor injection.
    AppConfig.java
    package in.sp.config;
    
    import in.sp.beans.Car;
    import in.sp.beans.Engine;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan(basePackages = "in.sp.beans")
    public class AppConfig 
    {
        @Bean
        public Engine engine()
        {
            return new Engine(); // Manually creating the Engine bean
        }
    
        @Bean
        public Car car()
        {
            return new Car(engine()); // Manually injecting the Engine bean into Car
        }
    }
    MainApp.java
    package in.sp.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import in.sp.beans.Car;
    import in.sp.config.AppConfig;
    
    public class MainApp
    {
    	public static void main(String[] args) 
    	{
    		// Loading Spring context from annotations
    		ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            
    		Car car = context.getBean(Car.class);
            
    		car.drive();
    	}
    }
    Below is the output
    Output:
    Engine started...
    Car is running...


  • Program 2
    Now we are going to create above same program for Constructor Injection using XML Configurations.
    Engine.java
    package in.sp.beans;
    
    public class Engine 
    {
        public void start() 
        {
            System.out.println("Engine started...");
        }
    }
    Car.java
    package in.sp.beans;
    
    public class Car 
    {
        private final Engine engine;
    
        // Dependency Injection via Constructor
        public Car(Engine engine) 
        {
            this.engine = engine;
        }
    
        public void drive() 
        {
            engine.start();
            System.out.println("Car is running...");
        }
    }
    NOTE : Its good practice to use final keyword for fields (private final Engine engine;) that should not change after initialization, especially for dependencies injected via constructor injection.
    applicationContext.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- Engine bean -->
        <bean id="engine" class="in.sp.beans.Engine" />
    
        <!-- Car bean with constructor injection for Engine -->
        <bean id="car" class="in.sp.beans.Car">
            <constructor-arg ref="engine" />
        </bean>
    
    </beans>
    NOTE : Here we have used <constructor-arg ref="----" /> tag for Constructor Injection.
    MainApp.java
    package in.sp.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import in.sp.beans.Car;
    
    public class MainApp
    {
    	public static void main(String[] args) 
    	{
    		// Loading Spring context from annotations
    		ApplicationContext context = new ClassPathXmlApplicationContext("in/sp/resources/applicationContext.xml");
            
    		Car car = context.getBean(Car.class);
            
    		car.drive();
    	}
    }
    Below is the output
    Output:
    Engine started...
    Car is running...

Advantages of Constructor Injection

  • Immutability: Constructor Injection allows setting dependencies only once, at construction, which promotes immutability.
  • Clarity: CDI clearly communicates that a class requires certain dependencies to function, making the code self-documenting.
  • Reliability: As dependencies are initialized once during object creation, it reduces the risk of dependencies being altered later, which enhances code reliability.
  • Easier Testing: CDI simplifies testing by allowing mocks to be injected during test setup.