Dependency Injection and IoC

Bharath K C
5 min readJun 14, 2021

--

In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies. Inversion of control is a programming principle. IoC inverts the flow of control compared to traditional control flow. In IoC, a computer program receives the flow of control from a framework. IoC means to create instances of dependencies first and then an instance of the class. In this article Dependency Injection and Inversion of control, concepts are discussed related to the Spring framework.

Spring Framework

The Spring Framework is an application framework and inversion of control container for the Java platform. Spring handles the infrastructure so developers can focus on the application.

The spring container is responsible for instantiating, configuring, and assembling the spring beans. A bean is an object that is created and managed by a Spring IoC container. The container gets its instructions on what objects to instantiate, configure and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code.

Types of Configuration

Dependency Injection

Dependency Injection is a design pattern that implements the inversion of control principle for resolving dependencies. It allows the programmer to remove hard-coded dependencies so that the application becomes loosely coupled. A loosely coupled system is one in which each of its components has very little or no knowledge of other components present in the system.

public class Student {
private Address address;
public Student() {
address = new Address();
}
}

Consider the above example. Student class requires an Address object and it is responsible for initializing and using the Address object. If the Address class constructor is changed in the future then we have to make changes in the Student class also. This approach makes tight coupling between Student and Address objects. We can resolve this problem using dependency injection design pattern. i.e. Address object will be implemented independently and will be provided to the Student when Student is instantiated by using constructor-based or setter-based dependency injection.

Types of Dependency Injection

Constructor-based Dependency Injection: Constructor-based dependency injection is the process of passing the dependency to a dependent object via a constructor. Consider an example. There are two classes Student and Address. In the Spring configuration file, we define the Address bean and pass this as an argument in the Student class using the constructor argument element.

// student.javapackage com.example;public class Student {
private String name;
private String rollNo;
private String className;
private Address address;

public Student(Address address){
this.address = address;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Address getAddress() {
return address;
}

}

this is an example class. The address object depends on the Student object.

// Address.javapackage com.example;

public class Address {
private String addLine;
private String city;
private String state;
private String country;

public String getAddLine() {
return addLine;
}
public void setAddLine(String addLine) {
this.addLine = addLine;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}

}

The applicationContext.xml file.

<?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-3.0.xsd">

<bean id="student" class="com.example.Student">

</bean>

<bean id="address" class="com.example.Address">
</bean>

</beans>

The application context XML is a standard spring context file that contains all beans and the configuration that are common among all the servlets. The classes that need to be instantiated are written inside the bean tag(as shown in the above code block). Id is unique to each bean and if no id is given the spring container will provide the default id which class name with the first letter in lowercase. The class should be provided with a fully qualified class name.

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
public static void main(String[] args) {
//Get ApplicationContext using spring configuration file.
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//Get Student bean object from ApplicationContext instance.
Student student = (Student) context.getBean("student");
// use student object to call all get methods from Student class//Get Address from Student Object.
Address studentAddress = student.getAddress();
// use studentAddress object to call get methods from Address class

The AppliactionContext extends the BeanFactory and so provides all those features as that a BeanFactory. The spring container is responsible for instantiating and managing the lifecycle of spring beans. The ClassPathXmlApplicationContext is a class that implements the ApplicationContext interface. In the above code block, the getBean() method gives the object of the student class. The spring container gives Address instance because Address instance depends on the student class.

In setter injection, The reference is created inside the setter method and configured in the XML file to give that instance of the class.

Configuration of XML file for setter injection
<bean id="myFortuneService" class="com.luv2code.springdemo.HappyFortuneService">
</bean>
<bean id="myCricketCoach" class ="com.luv2code.springdemo.CricketCoach"<property name="fortuneService" ref="myFortuneService" /></bean>

The classes are simple. The setter method(setFortuneService) in CricketCoach has the HappyFortuneService reference. The spring container will create an instance HappyFortuneService and then creates an instance of CricketCoach and calls setFortuneService method(inside the property tag name is used to call the setter method).

Some annotations used in Spring Annotation-based container configuration

@Required: It's a method-level annotation and applied to the setter method of a bean. This annotation simply indicates that the setter method must be configured to be dependency injected with a value at configuration time.

@Autowored: This annotation can be used with a constructor, setter, or filed injection to mark a dependency that spring is going to resolve and inject.

@Primary: This annotation is used to give higher preference to a bean when there are multiple beans of the same type.

@Qualifier: this annotation is used to resolve a situation where more than one bean is created of the same type and we want to wire only one of them. @Qualifier annotation is used with @Autowired annotation.

Conclusion

This article covers the basic terms related to IoC and Dependency Injection. For more information refer https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core.

--

--

No responses yet