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

Setter Method Injection in Spring


Introduction

  • Setter Method Injection is a form of Dependency Injection where an object’s dependencies are provided through setter methods after the object’s creation.

  • In Setter Method Injection, dependencies are passed via public setter methods, making them optional and allowing flexibility in providing or changing dependencies after the object has been created.
  • This approach allows dependencies to be injected or modified after instantiation. If a dependency is not supplied, the object can still be created but might not function fully until all necessary dependencies are set.

  • Now we will create 2 programs for Setter Method 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 setter method in Car class.
    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;  // Engine dependency
    
        // Setter method for dependency injection
        public void setEngine(Engine engine) 
        {
            this.engine = engine;
        }
    
        public void drive() 
        {
            engine.start();
            System.out.println("Car is running...");
        }
    }
    NOTE : Do not use final keyword for fields (i.e. private final Engine engine;) like we used for constructor injection because the nature of final conflicts with the behavior of setter 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()
        {
            Car car = new Car();  // Creating Car bean manually
            car.setEngine(engine());  // Manually setting the Engine dependency through setter
            return 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 Setter Method 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 Engine engine;
    
        // Dependency Injection via Setter Method
        public void setEngine(Engine engine) 
        {
            this.engine = engine;
        }
    
        public void drive() 
        {
            engine.start();
            System.out.println("Car is running...");
        }
    }
    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 setter injection for Engine -->
        <bean id="car" class="in.sp.beans.Car">
            <property name="engine" ref="engine" />
        </bean>
    
    </beans>
    NOTE : Here we have used <property name="----" ref="----" /> tag for Setter Method 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 XML configuration
            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 Setter Method Injection

  • Flexibility: Setter Method Injection allows dependencies to be changed or updated after object creation, which can be useful if we need to reconfigure dependencies at runtime or in specific scenarios.
  • Optional Dependencies: Setter injection makes it easy to declare optional dependencies. Unlike Constructor Injection, which requires all dependencies to be provided at instantiation, Setter Injection allows for dependencies to be set only if needed.
  • Better Handling of Circular Dependencies: In complex applications, Setter Injection can help manage circular dependencies more gracefully, as objects can be created first and dependencies injected later.
  • Ease of Reconfiguration: Since dependencies can be modified after object creation, Setter Injection is well-suited for situations where dependencies might vary based on context or conditions.
  • Supports Legacy Code: Setter Injection can be more convenient when integrating with legacy code or frameworks that do not allow modification of existing constructors, as it enables dependency injection without altering the constructor signature.