How is Dependency injection applied to Spring Boot (part 1)?

Tram Ho

The next article will discuss the super important concept is Dependency injection, and how to use it in Spring Boot.

1. Module coupling

1.1. What is Coupling?

First of all, it is necessary to talk briefly about the concept of coupling module . Coupling can be understood as the relationship between two modules, two objects together, with mutual dependencies.

And coupling has two types:

  • Tight coupling: two modules are closely linked, difficult to separate
  • Loose coupling: weak, discrete bond

In the program, there will usually be many separate modules, each with its own functions, and a relationship (HAS-A in OOP).

For example, two modules Car and Engine , car depend on engine can run. The code is shown as follows.

1.2. Principle of dependencies

We have just gone through the concept of coupling. Next here are important principles related to it that you need to remember.

In order for the code to be easy to maintain and modify, the principle is to reduce dependencies between modules.

That means turning the relationship between them from tight coupling to loose coupling.

As the code above, the dependency between Car and ChinaEngine very strong. This leads to many difficulties:

  • Want to change the engine, need to fix the Car class
  • It is impossible to have two Car using different Engine
  • It is more difficult to test the modules

In the program there are not only 1, 2 modules like the above example, but there are many. Therefore, if the modules stick too tightly together, it will be difficult to maintain.

2. Dependency inversion principle

2.1. Dependency inversion principle

This is Principle # 5 of SOLID principles, corresponding to the letter D. Designed to design the modules in the program, in such a way that there are as few dependencies as possible.

The DI principle has two main ideas:

  • High-level modules should not depend (directly) on low-level modules. Both should depend on abstraction (of OOP).
  • Abstraction should not be dependent on details, but vice versa.

Okay, that sounds pretty abstract. Let’s take the analysis slowly, step by step.

First, you need to understand what dependency is. The example above the Car class depends on the ChinaEngine class, so ChinaEngine is a dependency of the Car . At this point, we say Car is a high-level module, ChinaEngine is a low-level module.

2.2. The first point of the DI principle

Reviewing the above code, it can be seen that the code violates point 1 of the DI principle. The reason is because Car was directly dependent on ChinaEngine (because the Car class code uses ChinaEngine ),

To conform to the DI principle, let’s fix it as follows. By making both modules depend on abstraction (in OOP it is usually interface).

The above code takes advantage of the OOP polymorphism to switch between Engine types without error.

2.3. Code explanation

As above, after editing, both Car and ChinaEngine depend on the Engine interface (representing abstraction). This is true to the principle that DI sets out:

  • ChinaEngine is an Engine type. Engine has any methods, ChinaEngine must implement it all. Therefore, when installed in the Car , the functions of the engine are the same and are in the Engine .
  • Car uses Engine as an engine, instead of a specific class. Therefore, as long as the engine belongs to the Engine (implement this interface), it can be attached to the Car .

At this point, the relationship between Car and ChinaEngine has been much looser. And we can easily add another type of engine as follows.

But then how to use, if there are two types of Engine , how do I know which one to attach to the Car ?

Yes, but this will be done when instantiating the Car object. That means when we create a Car , we attach an Engine to it. Reviewing the first code, we have ChinaEngine attached ChinaEngine to the Car within the Car itself, in fact it must be done outside, when creating the Car . That is the difficulty when the connection between them is too hard.

And as the example code below, when the relationship becomes more loosely, we can create 2 different Car objects, with two different Engine types easily.

Above example we implement attach Engine to Car in the constructor. This is called constructor-based injection , we will discuss in more detail in the next section.

2.4. The second point of the DI principle

The second point of the DI principle is pretty straightforward if you master OOP. Specifically, the principle “abstraction should not depend on details, but vice versa” means that abstraction only takes the properties, the most common actions, regardless of the details within them.

Returning to the Engine example above, we just need to know how abstraction Engine has a run method, and how the different types of engines perform run (details) do not care.

Then inside the Car class, it doesn’t care how the engine runs. It just needs to know that when doing some actions, the car will run, that’s all.


Part 1 of this article is over. Please look forward to the next part. Have any questions, please comment below, because this is quite an important part of learning Spring.

Share the news now

Source : Viblo