The general understanding and simple writing of Spring containers

Spring IOC

Posted by chyuan on 2022-11-13
Estimated Reading Time 6 Minutes
Words 985 In Total

Problem description:

  1. Beginners are always confused when they are new to ‘Spring’ containers.
  2. I don’t know why the object can be used directly “@Autowired” where it is wanted.
  3. This article is a popular talk about how to use ‘@Autowired’ to get the object you want.

Think about why ‘Spring’ containers were introduced?

  1. In actual development work, developers need to write a lot of ‘classes’ to complete a function and complete a transaction.
  2. To use a ‘Class’ to work, we first have to ‘new’ an instance object of this ‘Class’, right, and will request space from the ‘JVM’ (Java Virtual Machine) before we can execute the non-static code sections written in the ‘Class’.
  3. If there is no ‘Spring’ container, then every time the ‘new’ object finishes working, it has to be freed to avoid taking up space, right?

Then the problem comes, so repeatedly to the commonly used Class to new objects, to release objects, but not to let these commonly used Class keep an object for the system resource overhead is small. So the ‘Spring’ container came into being. It is to solve the development pain points here.

  1. The actual function of the ‘Spring’ container, which teachers should have talked about, is to carry the object.
  2. Be specific, for example, you can think of the ‘Spring’ container as a toolbox that can contain hammers, pliers, wrenches, tape measures, etc.

In fact, the ‘Spring’ container mainly does three things.

  1. Create and persist object instances. **
  2. Tag object instances for management. **
  3. Provides an interface to the outside world to get the object through the markup of the instance object. **

Practice, dry! Don’t instigate:

Let’s implement a very rough Spring container with simple code, and you can understand it by reading it along.

Coding Preparation:

  1. ‘java JDK 1.8’ version
  2. ‘IDE’ tool, preferred ‘IntelliJ IDEA’ (this is charged, a little expensive, of course, I won’t tell you the way to crack, I publicly support the genuine version), or ‘Eclipse’, it is not recommended to use ‘MyEclipse’

Prepare a few classes:

Customize registration annotations:

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.demo.annotation;

import java.lang.annotation.*;

/**
* Created by CN94740284 on 2/9/2020.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyComponent {
}

Customize binding annotations:

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.demo.annotation;

import java.lang.annotation.*;

/**
* Created by CN94740284 on 2/9/2020.
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
}

To register and bind a data binder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* Created by CN94740284 on 11/20/2020.
*/
public class Register {

private static Container container = new Container();

private static Container getContainer() {
return container;
}

private static boolean regist(Class<?> clzz){
Container container = Register.getContainer();
Map<String, Object> tools = container.getTools();
Object o = null;
try {
o = clzz.newInstance();
tools.put(clzz.getName(),o);
return true;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}

private static boolean myAutowired(){
Map<String, Object> tools = Register.getContainer().getTools();

tools.forEach((key,value)->{
Class<?> clzz = value.getClass();
Field[] fs = clzz.getDeclaredFields();
try {
bindFields(value, fs, tools);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});

return true;
}

public static <T> T getBean(Class<T> clzz){
Map<String, Object> tools = Register.getContainer().getTools();
T t = (T) tools.get(Test.class.getName());
return t;
}

private static boolean bindFields(Object obj,Field[] fields,Map<String, Object> tools) throws IllegalAccessException {
for (Field field : fields) {
//Gets the annotation of type T on the property
if(field.isAnnotationPresent(MyAutowired.class)) {
Class<?> type = field.getType();
Object tool = tools.get(type.getName());
if(tool!=null){
field.setAccessible(true);
field.set(obj,tool);
}else{
return false;
}
}
}
return true;
}

public static boolean registAndAutoBind(ScanFileTool t) {
t.findClassLocal(ScanFileTool.STARATEGY_PATH);
List<Class<? extends String>> eleStrategyList = t.getEleStrategyList();

// Register the object
if(eleStrategyList!=null && eleStrategyList.size()>0){
eleStrategyList.forEach((clzz)->{
if(clzz.isAnnotationPresent(MyComponent.class)){
Register.regist(clzz);
}
});
}

// Bind the property object
Register.myAutowired();

return true;
}
}

Using @MyComponent Annotations:

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.demo.tools;

import com.example.demo.annotation.MyComponent;

/**
* Created by CN94740284 on 11/20/2020.
*/

@MyComponent
public class Hamer extends Tool {

}

Prepare the abstract class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.demo.tools;

import com.alibaba.fastjson.JSON;

/**
* Created by CN94740284 on 11/20/2020.
*/
public abstract class Tool {

public String getToolName() {
return getClass().getName();
}

@Override
public String toString() {
return JSON.toJSONString(this);
}
}

Register @MyComponent with custom annotations and inject data using @MyAutowired bindings

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

import com.example.demo.annotation.MyAutowired;
import com.example.demo.annotation.MyComponent;
import com.example.demo.tools.Hamer;

/**
* Created by CN94740284 on 11/20/2020.
*/
@MyComponent
public class Test {

@MyAutowired
private Hamer hamer;

public void printHamerName(){
System.out.println("Test : "+hamer.getToolName());
}

}

The above methods and types of safe ways to eat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.example.demo;

import com.example.demo.register.Register;
import com.example.demo.tools.test.Test;
import com.example.demo.utils.ScanFileTool;

import java.net.URISyntaxException;

public class DemoApplication {

public static void main(String[] args) throws URISyntaxException {

// Scan objects with custom annotations based on package paths
ScanFileTool t = new ScanFileTool();

// Register and bind
boolean b = Register.registAndAutoBind(t);

// Similar to SpringUtils.getBean
Test test = Register.getBean(Test.class);

// Call the object method
test.printHamerName();

}

}

The process is as follows:

1
2
3
graph TD
A[Scan PackageScanFileTool] -- Register --> B[Container Map] -- Bind --> C[Bind Object] --> D[Container ready] -- according to class name --> E[Get/Use Object]

Related code download link: [Click here to download] (msc.zip)


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !