4

zero, preface

It has been two years since I started learning SpringBoot on the first day. My ability to move bricks has been continuously enhanced in the past two years, but the theoretical level is still a novice with zero foundation.
Therefore, the way to break the bottleneck is to read more books, read more theoretical knowledge, and then apply it in practice, just like the seniors.

So I started to learn one of the two big features of Spring - of Control (IoC) .

Before that, we need to understand what is dependency .
If the successful operation of A must call B, then it can be said that B is A's dependent .
image.png
For example, if the Controller wants to call the method of the Service, it must have a reference (pointer) of the Service object that can be operated. At this time, the Controller depends on the Service.
image.png

1. Under normal circumstances, how is the object of the dependency instantiated?

The most traditional way is: direct new object, whoever uses new.
E.g:
If you want to complete a student management function, you need StudentController (controller), StudentService (service) and StudentRepository (warehouse), and students and classes are ManyToOne, so KlassService (class service) and KlassRepository (class warehouse) may be called.
When implementing class management, there are similar dependencies.
as the picture shows:
image.png
If the Student Service wants to view student information, it needs to:

//  实例化学生仓库
private StudentRepository studentRepository = new StudentRepository();
// 实例化班级服务和班级仓库,从而实现关联查询
private KlassService klassService = new KlassService();
private KlassRepository klassRepository = KlassRepository();

And, if the class Service wants to view class information, it needs to:

//  实例化班级仓库
private KlassRepository klassRepository = KlassRepository();
// 实例化学生服务和学生仓库,从而查看每个班级里的学生
StudentService studentService = new StudentService();
private StudentRepository studentRepository = new StudentRepository();

In addition, when the C layer calls the Service, it also needs to instantiate it:

StudentService studentService = new StudentService();

In this way, inter-component dependencies can indeed be achieved through the new object, but the problem is also obvious.

limitation

From a business logic point of view, controllers, services, and warehouses are all responsible for the processing and delivery of data streams, so they should all be singleton patterns. Repeated instantiation of these objects not only consumes redundant resources, but also interferes with internal Normal invocation of partial variables.
So in some cases, it is completely possible to share the instance objects of the same dependency globally.

One might say that it can be improved to only make its dependency calls in a specific component, and other components share these objects.
However, due to the uncertainty of business logic, it is difficult to determine the life cycle of components when writing,
Who will create, when to create, when to release, and whether it can be guaranteed that it will not be called when released, these are all questions.

In addition, there is another problem. When actually creating an object, it is not simply new, but some properties should be injected through the constructor.
But if two classes depend on each other, such an object cannot be new (a chicken-and-egg problem).

2. Inversion of Control

The literal meaning of inversion of control is that the original work of maintaining objects is done by developers. The so-called inversion is to hand over this process to the program itself.
Developers only need to tell Spring the dependencies between objects, and the implementation details are automatically completed by Spring through reflection.
By convention, we call components created through Spring IoC Beans.
image.png

There are three ways of dependency injection:

① set method injection

For example, StudentService is injected into StudentController

// 第一步,在类中声明依赖关系
StudentService studentService;

// 第二步,在类中声明一个set方法
public void setStudentService(StudentService studentService) {
    this.studentService= studentService;
}

// 第三步,在xml中”告诉“Spring如何依赖
<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="StudentController" class="test.lyx6666.controller.StudentController">
        <property name="studentService" ref="studentService" />
    </bean>

    <bean id="studentService" class="test.lyx6666.controller.studentService" />
</beans>

But this method is still quite troublesome. The author is ignorant of learning and has never written it. I have only seen it in the tutorial.

② Constructor injection

// 第一步,声明这个类是Spring组件,例如@RestController或@Service等
@RestController
@RequestMapping("student")
public class StudentController {
    ...
}

// 第二步,声明依赖关系的变量,必须为  private final 
private final StudentService studentService;

// 第三步,在构造函数中声明想要注入的变量
public StudentController(StudentService studentService) {
  this.studentService = studentService;
}

③ @Autowired injection

// 第一步,声明这个类是Spring组件,例如@RestController或@Service等
@RestController
@RequestMapping("student")
public class StudentController {
    ...
}

// 第二步,声明依赖关系的变量
StudentService studentService;

// 第三步,在依赖关系上加入@Autowired注解
@Autowired
StudentService studentService;

In short, Spring prepares a container for us to place these dependencies.
The so-called container is an item that holds things. In reality, containers include water cups, kettles, refrigerators, organizers and so on.
image.png

The Spring container provides space for these objects. When the objects need to be assembled, Spring will instantiate these objects in order according to the dependencies and place them in the container.
image.png
The objects in these containers will be maintained by Spring and follow the singleton pattern, that is, there is only one instance of this class globally.
When other objects also depend on objects already in the container, references (pointers) in the container are provided directly.

3. Summary

In short, IoC separates the invocation of objects from the maintenance of object relationships. When users use objects, they do not need to manually instantiate and assemble objects, and they no longer need to pay attention to its life cycle. They only need to focus on object functions. That's it.
In addition, IoC avoids redundant objects and reduces resource consumption through the singleton mode when needed, and allows beans to be shared, making the logic executed by the software more in line with business logic.
In fact, whether to use or not to use the singleton pattern is still adjusted according to specific business needs.

postscript

I once left the team for a period of time before the postgraduate entrance examination. At that time, in addition to reviewing, I also felt that I had encountered a bottleneck. At that time, I felt that the code could be understood, but I couldn’t remember it. The shallow code syntax and principles can be understood. But it is only limited to this. For deep-level knowledge, not only do you not understand, but more importantly, you don't know how to learn further, so the level stays in the state of half a bottle of vinegar for a long time.
Perhaps, this time I suddenly realized that "learning theory is a compulsory course", when I started to consciously and actively study, this bottleneck period has passed, at least my mentality has become much calmer, and I hope there will be more progress in the future. .

how did this article come about

To be precise, I first studied Teacher Liao Xuefeng's tutorial, and then re-written it based on my own understanding, just to deepen my understanding.
Therefore, there must be repeated content, not plagiarism.

References:

https://www.liaoxuefeng.com/wiki/1252599548343744/1308043627200545


LYX6666
1.6k 声望75 粉丝

一个正在茁壮成长的零基础小白