A brief summary of DI and DI containers

Nice to meet you. I'm still a young programmer with less than two years of experience, but I will gradually output what I have studied. If you have any mistakes, please let us know.

For the time being, I will summarize what I learned briefly about DI (DI container that implements it), which is the core system of the Java framework that I have somehow used so far, also as a test of posting.

What is DI?

Abbreviation for Dependency Injection. A software design pattern that implements the principles of IOC (Inversion of Control). Setting a class (temporarily called a component class) required for a certain class (temporarily called an interface class) (this setting operation is also called "injection"). By using DI, it is possible to separate the generation and dependencies of the instances that make up the logic from the interface class.

DI background

As the scale of application development grows, one logic is often implemented by combining multiple component classes. When that happens, the degree of coupling of the classes will gradually increase, and the cost of change due to partial implementation replacement will increase.

//Interface class that handles user-related processing
public class UserServiceImpl implements UserService {

	//Component class for data persistence
	private UserRepository userRepo;
	private AddressRepository addressRepo;

	/*constructor*/
	public UserServiceImpl() {
		this.userRepo = new UserRepositoryImpl();
		this.addressRepo = new AddressRepositoryImpl();
	}
}

When implementing such a class, it is necessary to have the component classes (UserRepositoryImpl and AddressRepositoryImpl) in advance. If these are incomplete, you will probably use a dummy class, but as the development scale grows, you can even replace the dummy class. The change cost will increase.

As a method of reducing the degree of coupling of such classes, we will implement it based on the concept of DI. Specifically, the instantiation of the component class inside the interface class is stopped, and the interface of the component class is received as an argument.

Java.UserServiceImpl


	/*constructor*/
	public UserServiceImpl(UserRepository userRepo,AddressRepository addressRepo) {
		this.userRepo = userRepo;
		this.addressRepo = addressRepo;
	}

Java.UserService call processing


	UserRepository userRepo = new UserReposiotryImpl();
	AddressRepository addressRepo = new AddressRepositoryImpl();
	UserService userService = new UserServiceImpl(userRepo,addressRepo);

This allows the caller to replace the dummy and component implementation class without changing the inside of UserServiceImpl. However, even with the above implementation, the setting of each component class for the interface class is done manually, and the change cost remains high. If possible, I would like to automate all of these settings as well. The DI container makes this possible.

What is a DI container?

The platform that automatically performs DI is called a DI container. The interface caller class (called the caller class) does not manually configure or implement the interface class as described above. You can get an instance of the interface class with the component class set via the DI container. Of course, if a component class depends on another component class, it will also configure it.

Implementation example

//Implementation by DI container function of Spring
//Completed all settings related to DI container in advance
public class UserServiceImpl implements UserService {

	@Inject
	private UserRepository userRepo;

	@Inject
	private AddressRepository addressRepo;
}

Benefits of using DI containers

Dependency resolution: Dependencies between interface and component classes can be resolved Scope control is possible: The timing from instantiation to destruction of the component class can be set individually. It is possible to control that some component classes are reused as singleton objects and some component classes are newly created each time. Providing AOP: When retrieving a component class from a DI container, common processing can be inserted uniformly. In addition, life cycle control is possible etc ...

Remarks

The relationship between an interface class and a component class is relative, and it is quite possible that a class that is an interface class for one class is a component class for another class.

Recommended Posts

A brief summary of DI and DI containers
Rails: A brief summary of find, find_by, where
A brief summary of Bootstrap features for beginners
Overview of Docker and containers
Summary of FileInputStream and BufferedInputStream
A brief summary of Rails association options (foreign_key, primary_key)
A brief explanation of commitAllowingStateLoss
A brief description of JAVA dependencies
Summary of hashes and symbols in Ruby
Summary of Java Math.random and import (Calendar)
A summary of only Rails tutorial setup related
[Java] Personal summary of classes and methods (basic)
A reminder of Docker and development environment construction
What are the advantages of DI and Thymeleaf?
Summary of Japan time setting and display method
Summary of frequently used commands in Rails and Docker
Summary of ToString behavior with Java and Groovy annotations
[For beginners] DI ~ The basics of DI and DI in Spring ~
[Rails] Volume that displays favorites and a list of favorites
Verification of the relationship between Docker images and containers
A record of a brief touch on GCP's Data Flow
About Bean and DI
Summary of OpenJDK sources
About DI of Spring ①
Summary of strong parameters
Summary of jar files
About DI of Spring ②
Summary of information security
Summary of using FragmentArgs
Summary of using DBFlow
Summary of Java support 2018
The nth and n + 1st characters of a Ruby string
I tried JAX-RS and made a note of the procedure
Comparison of Web App for Containers and Azure Container Instances
Install Ruby 3.0.0 Preview 1 with a combination of Homebrew and rbenv