[toc]
为什么我们需要IOC#
IoC是随着近年来轻量级容器(Lightweight Container)的兴起而逐渐被很多人提起的一个名词,它 的全称为Inversion of Control,中文通常翻译为“控制反转”,它还有一个别名叫做依赖注入(Dependency Injection)
本质上就是:
如果某个Java对象里有一些成员
那么尽量不要把这些成员写死(例如某个成员的类型是A, 不要写死成A=new A1()或者A=new A2())
而要通过 构造器 或者get、set来注入进来
换句话说,在这个对象的实现中,我们看不到成员对象的具体赋值, 一切都通过外部来决定恒成员是什么
而在Spring里,这个构造器和get、set都通过IOC SerivceProvider来提供
这个图很经典
3种注入方式:#
-
构造方法注入:Ioc用构造方法去注入。
好处是一旦构造好了,就可以马上用。 而且只需要对应类名和参数列表。缺点是参数多的话会很麻烦。 -
setter方法注入: Ioc用setXXX去注入成员。
良好。易扩展。通过set去设置成员。 -
接口注入: 必须要实现接口,然后接口里方法的参数为真正传入的成员对象。这个方式不提倡,有侵入性,一旦新增,其他全要开
接口注入看了好几遍才想明白是啥意思,换个通俗易懂的解释:
- 构造方法注入: Ioc只要知道类名和构造参数, 即可给你用反射传进去,。
- set方法注入: Ioc只要类名和你有哪些成员, 即可写反射的代码给你注入,都是setXXX,处理方式不会有变动。
- 接口方注入: Ioc 必须知道你有哪些注入接口,才能给你注入。 比如你用Init(A a)来注入, 于是Ioc必须也指定init这个方法, 再加参数,才给给你注入
明显接口注入,如果init方法改名了,可能会造成大面积的注入修改(因为其他地方可能都用了Init去构造了,然后爆炸)
而构造和set方式几乎都是相同的注入操作,只要改入参和类名即可。
Q: 构造注入和set注入,哪个更好,为什么?#
A:
set注入更好。因为可以解决循环依赖问题
A中有成员B, B中有成员A, 如果都用构造方法注入,则A和B new的过程就存在循环依赖。
但是用set的话,就可以先生成A和B的实体,再分别通过set注入到成员中。
Q: spring解决循环依赖的过程?#
A:
-
开始初始化对象A
singletonFactories:(刚构造完,也没人用过)
earlySingletonObjects:(如果构造过且被别人依赖过,都放进ealy中)
singletonObjects:(已经完全构建和注入完成)
这3个缓存选取的优先顺序是从下往上。 -
调用A的构造,把A放入singletonFactories
singletonFactories:A
earlySingletonObjects:
singletonObjects: -
开始注入A的依赖,发现A依赖对象B
-
开始初始化对象B
-
调用B的构造,把B放入singletonFactories
singletonFactories:A,B
earlySingletonObjects:
singletonObjects: -
开始注入B的依赖,发现B依赖对象A
-
开始初始化对象A,发现A在singletonFactories里有,则直接获取A,
并把A放入earlySingletonObjects,把A从singletonFactories删除
singletonFactories:B
earlySingletonObjects:A
singletonObjects: -
对象B刚才拿到了A对象,依赖注入完成
-
对象B创建完成,把B放入singletonObjects(即完成创建了),
singletonFactories:
earlySingletonObjects:A
singletonObjects:B -
对象B注入给A,继续注入A的其他依赖,直到A注入完成
-
对象A创建完成,把A放入singletonObjects,
singletonFactories:
earlySingletonObjects:
singletonObjects:A,B -
循环依赖处理结束,A和B都初始化和注入完成
(Spring解决循环依赖的方法)[https://blog.csdn.net/lkforce/article/details/97183065]
IOC ServiceProvider#
就是如何相当于服务员
对于业务类,不需要知道自己的成员具体是谁
而如何确定自己的真正成员,来自于IOC SeviceProverdier
。它可以是一段代码,也可以是一组相关的类,甚至可以是比较通用的IoC框架或 者IoC容器实现
。Spring 的IoC容器就是一个提供依赖注入服务的IoC Service Provider
IOCSP的职责:
业务对象的构建管理,即怎么创建依赖对象
业务对象间 的依赖绑定, 即怎么确定谁依赖谁。
IOC SeviceProverdier的3种管理方式:#
1.
直接编码,例如写1个map来做 类->具体子类的对应关系。然后在写map.put. get之类的代码来自己主动注入
2.
文本文件(xml、配置文件),然后自己去getXMl或者getPropetris解析
3.
注解, 相当于不用自己写map的put、get, 而是通过某个框架的注解,确定注入方式,然后去在那个框架对应的代码或者配置文件中写就行了。 其实就是1、2的升级版,不用自己去做解析和存储操作,你只要去框架那里写对应依赖关系即可。