Inversion of Control and Dependency Injection with Spring

Shehara Pandithasekera
3 min readJan 3, 2023

--

Inversion of Control (IoC)

It is a principal that transfers the control of objects or portions of a program to a container or framework. In traditional programming, our code makes call to a library, but in this case, IoC enables a framework to take control of the flow of a program and make calls to our code.

Instead of a class creating a instance of a dependency, it gets any version of the dependency and it will work with it. Instead of creating what dependencies you need, you don’t worry about the dependencies as long as it adheres to the general type interface called.

💡 Loose coupling vs. Tight coupling Loose coupling refers to the goal of reducing inter-dependencies between components of a system; whereas Tight coupling refers to classes or objects that are dependent on one another.

Example :

public class ComplexAlgorithm{
BubbleSortAlgorithm bubbleSort = new BubbleSortAlgorithm();
}

In the code above, the ComplexAlgorithm class is tightly coupled with the BubbleSortAlgorithm class. Therefore, in order to use another sorting method, you will have to change the code in the ComplexAlgorithm class*.*

@Component 
public class ComplexAlgorithmGeneral{

@Autowired
private SortAlgorithmImpl sortAlgorithm;
}

In this code, it is referring to the more general interface which is SortAlgorithmImpl . Simply put, the ComplexAlgorithmGeneral class will use whatever sortAlgorithm we provide from the SortAlgorithmImpl class. This way we can easily decouple the execution of a task from its implementation.

Note : IoC enable you to use Spring framework. Using @Component and @Autowired will allow Spring to find the SortAlgorithmImpl implementation and inject that dependency to the ComplexAlgorithmGeneral class (Further explained in the Dependency Injection section below).

Dependency Injection (DI)

DI is a design pattern we can use to implement IoC. Connecting objects or “injecting” objects into other objects is done by an assembler.

Example : In traditional programming we would often create an object dependency like so…

public class PC{

private HardDrive pcHDD;
private Ram pcRam;

ToshibaHDD pcHDD = new ToshibaHDD();
}

Here the PC object is dependent on the HardDrive object.

In order to achieve loose coupling (One object is not totally dependent on another object), we can use the concept of abstraction. This is where for every ToshibaHDD class we create an abstract class or an interface called HardDrive. So that in the future, we can just change the type of the hard drive.

So the instantiation of this instance would be;

public class PC{

private HardDrive pcHDD;
private Ram pcRam;

HardDirve pcHDD = new ToshibaHDD();
}

There is still an issue with this resolve. Hard coding the instantiation will tightly couple these objects. Therefore, we need to inject the HardDrive dependency to this PC class. This can be done with Spring, where it will create this object and inject it into the class.

This is how you inject dependencies into objects with Spring.

@Component   
public class ToshibaHDD implements HardDrive{
//functionality
}

Adding @Component will make this class a component of the Spring framework, which will be generated as per requirement.

Adding @Autowired will connect the object with the components.

public class PC{

@Autowired
private HardDrive pcHDD;

}

This will immensely help with unit testing when it comes to development testing. You can easily create a mock object of the dependency object and test the class or unit that is requires testing. You need to make sure that the connection between these two objects are loosely coupled to achieve this.

--

--