无题

IOC(控制反转)和DI(依赖注入)是spring中的重要组成部分,下面是个人的一些理解,不代表官方。

1、IOC是什么?

IOC:全名是Inversion of Controller 中文解释是控制反转,不是什么技术,是一种设计思想。在java开发中IOC意味着你设计好的对象交给容器控制,而不是传统的在你对象内部直接控制。如何理解好IOC那?理解IOC的关键是要明确:“谁控制谁”、“控制什么”、为何是反转(有反转就应该有正转)哪些方面反转了,我们来分析一下:

1)谁控制谁,控制什么:传统的java SE程序设计,我们直接在对象内部new进行创建对象,是程序主动去创建对象,而IOC有专门的容器来创建这些对象,即由IOC容器来控制对象的创建;谁控制谁?当然是IOC容器控制对象,控制什么?主要是控制外部资源的获取(不只是对象包括比如文件等)。

2)为何是反转,那方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中直接获取依赖对象,也就是正转;而反转是由容器来帮忙创建和注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取反转了。

用图例说明一下,传统程序设计如下图1,都是主动去创建相关对象然后再组合起来:

  ![[be5f27613f427f80e7aa2a6e8ced0f93_MD5.jpg]]

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2所示

 ![[5b3f9c423e94b7506e57c9832309aadb_MD5.jpg]]

2、IOC(控制反转)做什么用?

IOC不是一种技术,是一种设计思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由程序内部主动创建对象依赖,从而导致类与类之间高耦合,难于测试;有了IOC容器后,把创建和查找依赖对象的控制权交给了容器,由容器注入组合对象,所以对象和对象之间是松耦合的,这样利于测试,也利于功能复用,更重要的是使得程序的整个体系结构变的非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

3、DI是什么?
 DI:Dependency Injection ,即依赖注入:是组件之间依赖关系由容器在运行期决定,形象的说,由容器动态的将某个依赖关系注入到组件之中。

4、DI(依赖注入)有什么用

依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键:谁依赖谁,为什么需要依赖,谁注入谁,注入了什么?

1)谁依赖谁:当然是应用程序依赖IOC容器

2)为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源

3)谁注入谁:IOC容器注入应用程序的某个对象,应用程序依赖的对象

4)注入了什么:注入某个对象依赖的外部资源(包括对象,资源,常来数据)

IoC和DI什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。  

5、怎么用?

整体如图:

![[c9b4f5660d31f3fe12e6fcdafc157127_MD5.png]]

代码如下:

1、Servelt转ApplicationContext:(1)获取applicationContext上下文(2)初始化handlerMapper

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
package com.zmc.spring.framework.context;

import com.zmc.spring.framework.annotation.MCAutowried;
import com.zmc.spring.framework.annotation.MCController;
import com.zmc.spring.framework.annotation.MCService;
import com.zmc.spring.framework.beans.MCBeanWrapper;
import com.zmc.spring.framework.beans.config.MCBeanDefinition;
import com.zmc.spring.framework.beans.support.MCBeanDefinitionReader;
import com.zmc.spring.framework.beans.support.MCDefaultListableBeanFactory;
import com.zmc.spring.framework.core.MCBeanFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author zhangmc
* @create 2021/11/9 18:10
*/
public class MCApplicationContext implements MCBeanFactory{

private MCDefaultListableBeanFactory registry = new MCDefaultListableBeanFactory();

//三级缓存(终极缓存) key beanName(类名) value BeanWrapper包装类
private Map<String,MCBeanWrapper> factoryBeanInstanceCache = new HashMap<String, MCBeanWrapper>();

//key 类名 value 反射的实例对象
private Map<String,Object> factoryBeanObjectCache = new HashMap<String, Object>();

private MCBeanDefinitionReader reader;

public MCApplicationContext(String... configLocations) {

//1、加载配置文件
reader = new MCBeanDefinitionReader(configLocations);

try {
//2、解析配置文件,把所有的配置信息封装成BeanDefinition对象
List<MCBeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
//3、所有的配置信息缓存起来
this.registry.addBeanDefinitionMap(beanDefinitions);
//4、加载非延迟加载的所有Bean
doLoadInstance();
} catch (Exception e) {
e.printStackTrace();
}
}

private void doLoadInstance(){
//循环调用getBean()
for (Map.Entry<String,MCBeanDefinition> entry : this.registry.beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
if(!entry.getValue().isLazyInit()){
getBean(beanName);
}
}
}

// @Override
public Object getBean(Class className) {
return getBean(className.getName());
}

//从IOC容器中获取一个Bean对象
// @Override
public Object getBean(String beanName) {
//1、先拿到BeanDefinition对象
MCBeanDefinition beanDefinition = registry.beanDefinitionMap.get(beanName);
if(beanDefinition == null){
return null;
}
//2、反射实例化对象
Object instance = instantiateBean(beanName,beanDefinition);

//3、将返回的对象封装到BeanWrapper
MCBeanWrapper beanWrapper = new MCBeanWrapper(instance);

//4、执行依赖注入
populateBean(beanName,beanDefinition,beanWrapper);

//5、保存到IOC容器中
this.factoryBeanInstanceCache.put(beanName,beanWrapper);

return beanWrapper.getWrapperInstance();
}

//反射实例化对象
private Object instantiateBean(String beanName,MCBeanDefinition beanDefinition){
String className = beanDefinition.getBeanClassName();
Object instance = null;
try {
//jvm查找 并加载指定的类
Class<?> clazz = Class.forName(className);
//通过反射得到实例化对象
instance = clazz.newInstance();

//如果是代理对象,触发AOP的逻辑

this.factoryBeanObjectCache.put(beanName,instance);

} catch (Exception e) {
e.printStackTrace();
}

return instance;
}

private void populateBean(String beanName,MCBeanDefinition beanDefinition,MCBeanWrapper beanWrapper){
//获取实例化对象
Object instance = beanWrapper.getWrapperInstance();
//获取加载类
Class<?> clazz = beanWrapper.getWrapperClass();
//判断是否是Controller和Service的注解
if(!(clazz.isAnnotationPresent(MCController.class) || clazz.isAnnotationPresent(MCService.class))){
return;
}
//遍历 忽略字段的修饰符 不管你是 private / protected / public / default
for (Field filed : clazz.getDeclaredFields()){
//过滤非Autowired注解的
if(!filed.isAnnotationPresent(MCAutowried.class)){
continue;
}
MCAutowried autowried= filed.getAnnotation(MCAutowried.class);
String autowriedBeanName = autowried.value().trim();
if("".equals(autowriedBeanName)){
autowriedBeanName = filed.getType().getName();
}

//代码反射面前就是裸奔
//强制访问 强吻
filed.setAccessible(true);

try {
if(this.factoryBeanInstanceCache.get(autowriedBeanName) == null){
continue;
}

//相当于 demo.action.MyAction.
filed.set(instance,this.factoryBeanInstanceCache.get(autowriedBeanName).getWrapperInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

public int getBeanDefinitionCount(){
return this.registry.beanDefinitionMap.size();
}

public String[] getBeanDefinitionNames(){
return this.registry.beanDefinitionMap.keySet().toArray(new String[0]);
}
}

2、ApplicationContext 上下文对象

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
package com.zmc.spring.framework.context;

import com.zmc.spring.framework.annotation.MCAutowried;
import com.zmc.spring.framework.annotation.MCController;
import com.zmc.spring.framework.annotation.MCService;
import com.zmc.spring.framework.beans.MCBeanWrapper;
import com.zmc.spring.framework.beans.config.MCBeanDefinition;
import com.zmc.spring.framework.beans.support.MCBeanDefinitionReader;
import com.zmc.spring.framework.beans.support.MCDefaultListableBeanFactory;
import com.zmc.spring.framework.core.MCBeanFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author zhangmc
* @create 2021/11/9 18:10
*/
public class MCApplicationContext implements MCBeanFactory{

private MCDefaultListableBeanFactory registry = new MCDefaultListableBeanFactory();

//三级缓存(终极缓存) key beanName(类名) value BeanWrapper包装类
private Map<String,MCBeanWrapper> factoryBeanInstanceCache = new HashMap<String, MCBeanWrapper>();

//key 类名 value 反射的实例对象
private Map<String,Object> factoryBeanObjectCache = new HashMap<String, Object>();

private MCBeanDefinitionReader reader;

public MCApplicationContext(String... configLocations) {

//1、加载配置文件
reader = new MCBeanDefinitionReader(configLocations);

try {
//2、解析配置文件,把所有的配置信息封装成BeanDefinition对象
List<MCBeanDefinition> beanDefinitions = reader.loadBeanDefinitions();
//3、所有的配置信息缓存起来
this.registry.addBeanDefinitionMap(beanDefinitions);
//4、加载非延迟加载的所有Bean
doLoadInstance();
} catch (Exception e) {
e.printStackTrace();
}
}

private void doLoadInstance(){
//循环调用getBean()
for (Map.Entry<String,MCBeanDefinition> entry : this.registry.beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
if(!entry.getValue().isLazyInit()){
getBean(beanName);
}
}
}

// @Override
public Object getBean(Class className) {
return getBean(className.getName());
}

//从IOC容器中获取一个Bean对象
// @Override
public Object getBean(String beanName) {
//1、先拿到BeanDefinition对象
MCBeanDefinition beanDefinition = registry.beanDefinitionMap.get(beanName);
if(beanDefinition == null){
return null;
}
//2、反射实例化对象
Object instance = instantiateBean(beanName,beanDefinition);

//3、将返回的对象封装到BeanWrapper
MCBeanWrapper beanWrapper = new MCBeanWrapper(instance);

//4、执行依赖注入
populateBean(beanName,beanDefinition,beanWrapper);

//5、保存到IOC容器中
this.factoryBeanInstanceCache.put(beanName,beanWrapper);

return beanWrapper.getWrapperInstance();
}

//反射实例化对象
private Object instantiateBean(String beanName,MCBeanDefinition beanDefinition){
String className = beanDefinition.getBeanClassName();
Object instance = null;
try {
//jvm查找 并加载指定的类
Class<?> clazz = Class.forName(className);
//通过反射得到实例化对象
instance = clazz.newInstance();

//如果是代理对象,触发AOP的逻辑

this.factoryBeanObjectCache.put(beanName,instance);

} catch (Exception e) {
e.printStackTrace();
}

return instance;
}

private void populateBean(String beanName,MCBeanDefinition beanDefinition,MCBeanWrapper beanWrapper){
//获取实例化对象
Object instance = beanWrapper.getWrapperInstance();
//获取加载类
Class<?> clazz = beanWrapper.getWrapperClass();
//判断是否是Controller和Service的注解
if(!(clazz.isAnnotationPresent(MCController.class) || clazz.isAnnotationPresent(MCService.class))){
return;
}
//遍历 忽略字段的修饰符 不管你是 private / protected / public / default
for (Field filed : clazz.getDeclaredFields()){
//过滤非Autowired注解的
if(!filed.isAnnotationPresent(MCAutowried.class)){
continue;
}
MCAutowried autowried= filed.getAnnotation(MCAutowried.class);
String autowriedBeanName = autowried.value().trim();
if("".equals(autowriedBeanName)){
autowriedBeanName = filed.getType().getName();
}

//代码反射面前就是裸奔
//强制访问 强吻
filed.setAccessible(true);

try {
if(this.factoryBeanInstanceCache.get(autowriedBeanName) == null){
continue;
}

//相当于 demo.action.MyAction.
filed.set(instance,this.factoryBeanInstanceCache.get(autowriedBeanName).getWrapperInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

public int getBeanDefinitionCount(){
return this.registry.beanDefinitionMap.size();
}

public String[] getBeanDefinitionNames(){
return this.registry.beanDefinitionMap.keySet().toArray(new String[0]);
}
}

参考:浅谈对Spring IOC以及DI的理解_luoyepiaoxue2014的博客-CSDN博客_ioc和di

本文转自 https://blog.csdn.net/zhang2383906154/article/details/121331773?ops_request_misc=%257B%2522request%255Fid%2522%253A%25224e5f7713ece11e4c78889286db411330%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=4e5f7713ece11e4c78889286db411330&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-121331773-null-null.142^v102^pc_search_result_base5&utm_term=ioc%E5%92%8Cdi&spm=1018.2226.3001.4187,如有侵权,请联系删除。