Spring dependency injection

The process of injecting one bean into the other by spring container is known as dependency injection.

As the Spring container creates and manages beans so the container will have information on all the registered spring beans.

Check the inversion of control topic here https://getinputs.com/spring-inversion-of-control/

Say we register 2 beans Manager and Address with the spring container. Now if the Manager requires an instance of Address then the spring container can help to inject Address dependency in the Manager without any extra coding. Spring container will manage this for us using the concept of dependency injection.

Without spring

We as a developer have to take the responsibility to create and inject the beans.

Consider the example below where we have to manually create and inject the address dependency in Manager bean.

package com.getinputs;

public class Address {

  private String address;

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }
}
package com.getinputs;

public class Manager {

  Address managersAddress;

  public String getManagersAddress() {
    return managersAddress.getAddress();
  }

  public void setManagersAddress(Address managersAddress) {
    this.managersAddress = managersAddress;
  }
}
package com.getinputs;

public class Demo {

  public static void main(String[] args) {

    Address address = new Address();
    address.setAddress("civil lines delhi");

    Manager manager = new Manager();
    manager.setManagersAddress(address);

    System.out.println("Manager's address is : " + manager.getManagersAddress());
  }
}

Output : Manager's address is : civil lines delhi

In the above approach we as a developer have to create and inject the beans.

Using dependency injection spring reduces this extra work for us.

Types of dependency injection

Dependency injection can be done using Constructor injection and Setter injection.

Constructor injection

Spring container injects the required dependency using the constructor.

From the above example, we will remove the manual creation and injection of beans and we will make use of Spring constructor dependency injection.

We will update the Manager class to consume the Address bean using a constructor.

package com.getinputs;

public class Manager {

  Address managersAddress;

  public Manager(Address managersAddress) {
    this.managersAddress = managersAddress;
  }

  public String getManagersAddress() {
    return managersAddress.getAddress();
  }
}

Now we will create an applicationContext.xml file where we will define Address and Manager bean. Here we will inject the address bean in the manager using constructor injection.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Define your beans here -->
    
    <bean id="address" class="com.getinputs.Address">
       <property name="address" value="civil lines delhi"></property>
    </bean>
        
    <bean id="manager" class="com.getinputs.Manager">
       <constructor-arg ref="address"></constructor-arg>
    </bean> 
    
</beans>

Using the constructor-arg we have instructed the spring container to inject the address bean in the Manager bean via the constructor.

ref=address should match the bean id of Address bean.

Now we will create a bean factory using ClassPathXmlApplicationContext and then we will call the method of the registered bean.

package com.getinputs;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemoApp {

  public static void main(String[] args) {

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    Manager manager = context.getBean("manager", Manager.class);
    
    System.out.println("Manager's address is : " + manager.getManagersAddress());
    
    context.close();
  }
}

Output : Manager's address is : civil lines delhi

Here we do not have to create the Manager and Address bean manually instead spring container creates and injects the bean for us using the constructor injection.

Setter injection

Spring container injects the required dependency using the setter method.

In the above example we have injected the Address dependency using constructor injection now we will inject the same address dependency using setter injection.

We will update the Manager class to consume the Address bean using a setter method.

package com.getinputs;

public class Manager {

  Address managersAddress;

  public String getManagersAddress() {
    return managersAddress.getAddress();
  }

  public void setManagersAddress(Address managersAddress) {
    this.managersAddress = managersAddress;
  }
}

setManagersAddress will be the setter method to inject the Address dependency.

Now we will create an applicationContext.xml file where we will define Address and Manager bean. Also we will inject the address bean in the manager using setter injection.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Define your beans here -->
    
    <bean id="address" class="com.getinputs.Address">
       <property name="address" value="civil lines delhi"></property>
    </bean>
    
    <bean id="manager" class="com.getinputs.Manager">
       <property name="managersAddress" ref="address"></property>
    </bean>
    
</beans>

property name managersAddress should match the variable name in the Manager class. This property acts as a setter for Manager bean and address bean gets injected to Manager bean.

ref=address should match the bean id of Address bean.

We generate the setter method name by appending the word set and capitalizing the first letter of the property name (i.e) managersAddress. Hence the method name becomes setManagersAddress.

Now we will create a bean factory using ClassPathXmlApplicationContext and then we will call the method of the registered bean.

package com.getinputs;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringDemoApp {
  public static void main(String[] args) {

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    Manager manager = context.getBean("manager", Manager.class);
    
    System.out.println("Manager's address is : " + manager.getManagersAddress());
    
    context.close();
  }
}

Output : Manager's address is : civil lines delhi

Thus spring helps us to do the dependency injection using a constructor and setter. Here spring reduces a lot of boilerplate code and helps us to focus mainly on the business requirements.

This is all about spring dependency injection. I hope you found this article interesting and valuable. If you are having any concerns or questions about this article please comment below.

https://github.com/getinputs/samples/tree/main/dependency-injection-example

Leave a Comment