[For beginners] DI ~ The basics of DI and DI in Spring ~

Introduction

DI is an abbreviation for Dependency Injection, which is often translated as "Dependency Injection" in Japanese.

When I first came into contact with Spring when I was a new graduate, the first thing that came to my mind was the question mark. The connection with the concept of DI, DI container, and annotation in Spring didn't come to my mind.

This time, for myself as a beginner, I would like to briefly summarize the concept of DI and DI in Spring while organizing it in my own way.

What is Dependency?

I think it's easier to understand what a dependency is in the source code.

Main.java


public class Main {
    public int hoge() {
        var sub = new Sub();
        return sub.calculate();
    }
}

In the hoge method of Main class, an instance of Sub class is created and used. When there is such a Main class, it is expressed as "Main class depends on Sub class".

I think it's relatively easy to understand about addiction.

What is Injection?

In the previous example, an instance of the Sub class was created internally, but creating an instance externally and passing it to the class that uses it is called injection.

Here, an example using a constructor (constructor injection) is shown.

Main.java


public class Main {
    
    private Sub sub;
    
    public int hoge() {
        return sub.calculate();
    }
    
    //Constructor injection
    public Main(Sub sub) {
        this.sub = sub;
    }
}

Earlier, we created an instance of the Sub class in the hoge method, but in this example, the instance is received from the constructor.

By doing this, when you actually use the Main class,

var sub = new Sub();
var main = new Main(sub);

In the form of, the instance of Sub class is passed from outside the Main class.

The benefits of this will be described later.

What is a DI container?

When you hear the word container, you may think of Docker in modern times, but the container in DI container is different from the container used in the context such as Docker.

If you write it in one word without fear of misunderstanding, the DI container acts as a "container that manages the instance to be injected".

If you try to use the Main class without using the DI container as before, you will need an instance of the Sub class each time you use it.

If you use a DI container, it will manage this instance, so you don't have to create an instance each time.

DI container in Spring

In Spring, by specifying a class with annotations, you can specify an instance of that class as a target to be managed by the DI container.

Specifically, the annotations are as follows.

By the way, the instance managed by DI container can be obtained by using getBean method of ApplicationContext class.

In Spring, you can also set the scope of how long the DI container manages the instance.

The scopes that can be set are as follows, and the Scope annotation is used when setting.

The default of Spring is singleton, but by changing the setting, it is possible to destroy and reconfigure the instance managed by the container, for example, in session units.

One thing that beginners tend to do is to give the class a field that can change, despite the singleton. An example is shown below.

hogeService


@Service
public class hogeService {
    
    private String result;
    
    public int fuga(String suffix) {
        result = "test" + suffix;        
        return result;
    }
}

Since hogeService is annotated with Service and no scope is set, the scope is singleton.

As a result, you run the risk of changing the result field in another session, which makes it less thread-safe.

By making it a variable instead of a class field as shown below, it becomes a thread-safe implementation.

hogeService


@Service
public class hogeService {
    
    public int fuga(String suffix) {
        String result = "test" + suffix;        
        return result;
    }
}

DI in Spring

In Spring, you can DI by using Autowired annotation.

There are three injection methods, including the constructor injection mentioned earlier.

--Field injection --Setter injection --Constructor injection

Specifically, each is like this.

Main.java


public class Main {
    
    //Field injection
    @Autowired
    private Sub sub;
    
    public int hoge() {
        return sub.calculate();
    }
}

Main.java


public class Main {
    
    private Sub sub;
    
    public int hoge() {
        return sub.calculate();
    }
    
    //Setter injection
    @Autowired
    public setSub(Sub sub) {
        this.sub = sub;
    }
}

Main.java


public class Main {
    
    private Sub sub;
    
    public int hoge() {
        return sub.calculate();
    }
    
    //Constructor injection
    @Autowired
    public Main(Sub sub) {
        this.sub = sub;
    }
}

By annotating Autowired, it will inject instances from the DI container into the arguments of fields, methods and constructors.

By the way, when I inject myself, I write it using the RequiredArgsConstructor annotation of Lombok in the library, as described in the article here.

Benefits of DI

A common benefit is that unit tests are easier to write, I think this is true.

Here is the example at the beginning again.

Main.java


public class Main {
    public int hoge() {
        var sub = new Sub();
        return sub.calculate();
    }
}

If the calculate method of this Sub class needed to access the DB, unit testing of the Main class would be very difficult.

However, you can test it by mocking the instance you inject with DI. By the way, I use Mockito when using mock.

Summary

Finally, the following is a summary of DI and DI containers in one word.

DI: Passing an instance of a class that depends on a class from the outside DI container: A container that manages the instance to be injected

Using these has the advantage of making it easier to write tests and manage scope.

That's all for the content. We hope you find this article useful. Thank you for reading for me until the end.

References

Official documentation Core Technologies

Recommended Posts

[For beginners] DI ~ The basics of DI and DI in Spring ~
[For beginners] Quickly understand the basics of Java 8 Lambda
[For beginners] Explanation of classes, instances, and statics in Java
Spring validation was important in the order of Form and BindingResult
Memo of JSUG Study Group 2018 Part 2-Efforts for working specifications in the Spring and API era-
Set the number of seconds for fast forward and rewind in ExoPlayer
[Ruby basics] About the role of true and break in the while statement
[Rails] Articles for beginners to organize and understand the flow of form_with
Compare the speed of the for statement and the extended for statement.
Basics of threads and Callable in Java [Beginner]
What are the advantages of DI and Thymeleaf?
[Introduction to Java] Basics of java arithmetic (for beginners)
About DI of Spring ①
About DI of Spring ②
Spring Basics ~ DI Edition ~
Specify the encoding of static resources in Spring Boot
Until the use of Spring Data and JPA Part 2
Until the use of Spring Data and JPA Part 1
I summarized the types and basics of Java exceptions
List of frequently used Java instructions (for beginners and beginners)
[Ruby] Class nesting, inheritance, and the basics of self
Check the behavior of getOne, findById, and query methods in Spring Boot + Spring Data JPA
Docker monitoring-explaining the basics of basics-
Understand the basics of docker
The basics of Swift's TableView
I tried to summarize the basics of kotlin and java
Put the file in the properties of string in spring xml configuration
Accelerate testing of Validators that require DI in Spring Boot
A story packed with the basics of Spring Boot (solved)
Let's grasp the operation image (atmosphere) of the DI container of Spring
Java beginners briefly summarized the behavior of Array and ArrayList
Introductory hands-on for beginners of Spring 5 & Spring Boot 2 has been released
Create more Tabs and Fragments in the Fragment of BottomNavigationView
[Spring Data JPA] Can And condition be used in the automatically implemented method of delete?
[For Swift beginners] I tried to summarize the messy layout cycle of ViewController and View
Branch processing by the return value of RestTemplate and the status code of ResponseEntity in Spring Boot
I will explain the nesting of for statements that kill beginners
Basics of conditional branching and return
About the basics of Android development
Spring Boot for the first time
[For beginners] Summary of java constructor
Basics of sending Gmail in Ruby
Rock-paper-scissors game for beginners in Java
[Java] Get the dates of the past Monday and Sunday in order
Java for beginners, expressions and operators 1
Get a proxy instance of the component itself in Spring Boot
[For beginners] Run Selenium in Java
The basics of SpringBoot + MyBatis + MySQL
[For super beginners] The minimum knowledge you want to keep in mind with hashes and symbols
Java for beginners, expressions and operators 2
Let's consider the meaning of "stream" and "collect" in Java's Stream API.
This and that of the JDK
Explanation of Ruby on rails for beginners ⑤ ~ Edit and delete database ~
In order not to confuse the understanding of getters and setters, [Do not use accessors for anything! ]
[Android Studio] [For beginners] Let's roughly explain the screen and directories
[For beginners] Personally thinking about the cause of the error-the idea of ​​the solution
Form that receives the value of the repeating item in Spring MVC
Order of processing in the program
Spring AOP for the first time
[Android] Dynamically set the height of ListView with copy (for beginners)
Classes and instances Java for beginners