Posts Spring dependency injection
Post
Cancel

Spring dependency injection

What is DI ?

Hello audience, today I am going to discuss the spring dependency injection which is a design pattern used to implement the IoC in the Spring container.

Before talking about the implementation of this mechanism, I need first to define the dependency injection:

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.

That’s the Wikipedia definition, I know that’s not enough to understand, but I will give you an example to illustrate more this mechanism.

Suppose we have two classes, Computer and AsusHardDisk, and the class Computer uses some functionality of the AsusHardDisk class, so we need to create an object of AsusHardDisk inside the Computer to make calls to these functionalities, now we can say that class Computer has a dependency on class AsusHardDisk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.melhamra;

public class AsusHardDisk {
    
    private String someData = "some data";

    public String getSomeData() {
        return someData;
    }

    public void setSomeData(String someData) {
        this.someData = someData;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.melhamra;

public class Computer {

    private AsusHardDisk asusHardDisk = new AsusHardDisk();

    public AsusHardDisk getAsusHardDisk() {
        return asusHardDisk;
    }

    public void setAsusHardDisk(AsusHardDisk asusHardDisk) {
        this.asusHardDisk = asusHardDisk;
    }
}

Imagine if the class Computer no longer needs the class AsusHardDisk and wants to use HpHardDisk.

Now, we are facing a problem because we will need to recreate the class Computer with the new hard disk.

But when using the dependency injection you no longer need to instantiate the dependencies inside your classes, instead, the DI does all the work for you.
DI is considered as a middleman between a class that needs another, especially DI makes our class Computer independent from creating the HardDisk class.

In general, the IoC container lets you inject required objects in the runtime instead of the compile-time by the dependency injection, in order to make java classes independent of each other (loosely coupling) and frees them from object creation and maintenance.

Basically, in Spring there are two types of DI:

  • Setter dependency injection.
  • Constructor dependency injection.

Types of Spring dependency injection

1. Setter dependency injection

The dependencies will be injected with the help of the setters.
Example:

1
2
3
4
5
6
7
package com.melhamra;

public interface HardDisk {
    
    public String returnData();
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.melhamra;

public class AsusHardDisk implements HardDisk{

    private String someData = "some data from asusHardDisk";

    public void setSomeData(String someData) {
        this.someData = someData;
    }

    @Override
    public String returnData() {
        return someData;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.melhamra;

public class Computer {

    //Now we can work with any type of hard disk
    private HardDisk hardDisk;
    
    public Computer(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }

    public Computer() {}

    public HardDisk getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@org.springframework.context.annotation.Configuration
@ComponentScan
public class Configuration {

    @Bean("asusHardDisk")
    public AsusHardDisk getAsusHardDisk(){
        return new AsusHardDisk();
    }

    @Bean("computer")
    public Computer getComputer(){
        Computer computer = new Computer();
        // DI using the setter
        computer.setHardDisk(getAsusHardDisk());
        return computer;
    }
    
}

If we compare the class Computer used in the first section and the one used in this section we can conclude that:

  • The class Computer is no longer responsible for the instantiation of the dependencies.
  • The dependencies are created by the IoC container using DI.

2. Constructor dependency injection

In this, the DI will be injected with the help of constructors.

Example: Let us take the same example as of setter dependency injection but we will change just the configuration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.melhamra;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@org.springframework.context.annotation.Configuration
@ComponentScan
public class Configuration {

    @Bean("asusHardDisk")
    public AsusHardDisk getAsusHardDisk(){
        return new AsusHardDisk();
    }

    @Bean("computer")
    public Computer getComputer(){
        // DI using constructor
        Computer computer = new Computer(getAsusHardDisk());
        return computer;
    }
}

Note: All the codes above are available via this link : DI Demo

Process Flow: The process flow of bean instantiation and injection of dependencies is given in the picture below:

drawing

Summary

As you can see, DI has many benefits such as:

  • Helping in Unit testing.
  • Boiler plate code is reduced, as initializing of dependencies is done by the injector component.
  • Extending the application becomes easier.
  • Helps to enable loose coupling, which is important in application programming.

That was all for this blog, I hope you enjoy it and you understood all the points that we have touched on.

This post is licensed under CC BY 4.0 by the author.