如何理解IOC

Spring容器启动流程:https://javadoop.com/post/spring-ioc

控制反转,即将我们的对象控制权交给容器

ioc 的启动流程

1
2
3
4
5
6
7
8
9
10
init阶段:

scanPackage -> scanCreate(判断是否加了@component注解) -> wrapper 成 beanDefinnation(name)

create所有非Lazy的 bean阶段:
这时候涉及为一二级缓存:1级存放所有初始化好的bean,而2级存放所有半初始化好的bean 即创建好但依赖的组件没注入的bean
通过反射 构造方法去create Bean
执行一些加载前的
执行一些加载后的

手写IOC

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package com.lkl;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author: lkl
* @date: 2025/4/6 21:03
*/
public class ApplicationContext {
public ApplicationContext(String packageName) throws Exception {
initContext(packageName);
}
//一级缓存:存放完全初始化的bean
private HashMap<String,Object> ioc=new HashMap<>();
//二级缓存:存放还没初始化好的bean,但已经实例化了
private HashMap<String,Object> loadingIoc=new HashMap<>();
private HashMap<String,BeanDefinition> beanDefinitionHashMap=new HashMap<>();
protected Object createBean(BeanDefinition beanDefinition) {
String beanName = beanDefinition.getName();

if (ioc.containsKey(beanName)){
return ioc.get(beanName);
}
if (loadingIoc.containsKey(beanName)){
return loadingIoc.get(beanName);
}
//一,二级缓存没有的话,才会去创建bean
return doCreateBean(beanDefinition);
}

private Object doCreateBean(BeanDefinition beanDefinition) {
String name = beanDefinition.getName();
Constructor<?> constructor = beanDefinition.getConstructor();
//先默认是无参的
Object bean = null;
try {
bean = constructor.newInstance();
loadingIoc.put(name,bean);
//postProcess

//依赖注入
autowiredBean(bean,beanDefinition);

//afterProcess


//执行postConstructMethod
Method postConstructMethod = beanDefinition.getPostConstructMethod();
if (postConstructMethod!=null) {
postConstructMethod.invoke(bean);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
ioc.put(name,loadingIoc.remove(name));
return bean;
}

private void autowiredBean(Object bean, BeanDefinition beanDefinition) throws IllegalAccessException {
for (Field filed : beanDefinition.getAutowiredFields()) {
//通过类型 也可以通过名字
filed.setAccessible(true);
filed.set(bean,getBean(filed.getType()));
}
}

protected BeanDefinition wrapper(Class<?> type) {
BeanDefinition beanDefinition = new BeanDefinition(type);
if (beanDefinitionHashMap.containsKey(beanDefinition.getName())){
throw new RuntimeException("bean name重复----------");
}
beanDefinitionHashMap.put(beanDefinition.getName(),beanDefinition);
return beanDefinition;
}

protected void initContext(String packageName) throws Exception {
//先把所有的BeanDefinition加载
scanPackage(packageName).stream()
.filter(this::scanCreate)
.forEach(this::wrapper);
//再加载bean
beanDefinitionHashMap.values()
.forEach(this::createBean);
}
protected boolean scanCreate(Class<?> type){
return type.isAnnotationPresent(Component.class);
}
//扫包遍历
private List<Class<?>> scanPackage(String packageName) throws Exception {
System.out.println("start scan package -------------");
URL resource = this.getClass().getClassLoader().getResource(packageName.replace(".", File.separator));
Path path = Paths.get(resource.toURI());
List<Class<?>> classList=new ArrayList<>();
Files.walkFileTree(path, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path absolutePath = file.toAbsolutePath();
if (absolutePath.toString().endsWith(".class")) {
String replaceStr = absolutePath.toString().replace(File.separator, ".");
String className = replaceStr.substring(replaceStr.indexOf(packageName), replaceStr.length()-".class".length());
try {
classList.add(Class.forName(className));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//System.out.println(className);
}
return FileVisitResult.CONTINUE;
}
});

return classList;
}
//根据名字返回bean
public Object getBean(String name) {
if (name==null) {
return null;
}
Object bean = this.ioc.get(name);
if (bean!=null) {
return bean;
}
if (beanDefinitionHashMap.containsKey(name)){
return createBean(beanDefinitionHashMap.get(name));
}
return null;
}
//返回类型相同的bean
public <T> T getBean(Class<T> beanType) {
String beanName = beanDefinitionHashMap.values().stream()
.filter(a -> beanType.isAssignableFrom(a.getType()))
.map(BeanDefinition::getName)
.findFirst()
.orElse(null);
return (T)getBean(beanName);

}

public <T> List<T> getBeans(Class<T> beanType) {
return beanDefinitionHashMap.values().stream()
.filter(a -> beanType.isAssignableFrom(a.getType()))
.map(BeanDefinition::getName)
.map(this::getBean)
.map(bean->(T)bean)
.collect(Collectors.toList());

}
}

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
package com.lkl;

import com.lkl.sub.AutoWired;
import com.lkl.sub.PostConstruct;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author: lkl
* @date: 2025/4/6 21:21
*/
public class BeanDefinition {
private final String name;
private final Constructor<?> constructor;
private final Method postConstructMethod;
private final List<Field> autowiredFields;
private final Class<?> type;
public BeanDefinition(Class<?> type){
this.type=type;
Component annotation = type.getDeclaredAnnotation(Component.class);
this.name=annotation.name().isEmpty()? type.getName() : annotation.name();
try {

this.constructor=type.getConstructor();
this.postConstructMethod= Arrays.stream(type.getDeclaredMethods())
.filter(a->a.isAnnotationPresent(PostConstruct.class))
.findFirst()
.orElse(null);
this.autowiredFields = Arrays.stream(type.getDeclaredFields())
.filter(a->a.isAnnotationPresent(AutoWired.class))
.toList();
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}


}
public String getName(){
return name;
}
public Constructor<?> getConstructor(){
return constructor;
}

public Method getPostConstructMethod() {
return postConstructMethod;
}

public List<Field> getAutowiredFields() {
return autowiredFields;
}

public Class<?> getType() {
return type;
}

}