1.4 Spring 依赖注入(DI)和控制反转(IOC)详解
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:
https://www.cnblogs.com/bclshuai/p/11380657.html
1.1 Spring 依赖注入(DI)和控制反转(IOC)
1.1.1 作用
使用IOC和DI的作用是实现类之间的解耦。以往的开发中类相互依赖,使用对象时,根据类去new一个对象,如果类的构造函数发生改变,则所有new该对象的地方都要去修改,这就是一种强耦合。而Spring采用容器来创建对象和管理依赖关系。通过注解的方式将对象注入到引用对象的地方。实现了弱耦合。
1.1.2 概念理解
依赖注入(dependency injection)和控制反转(Inversion of Control),实际上是一实现解耦的机制,在开发大型项目时,肯定要创建多个类,而且类之间相互依赖错综复杂,往往牵一发而动全身,为了解除类之间的耦合,而采用IOC进行解耦,实现各个模块之间的独立开发,协同工作。例如机械手表中各个齿轮之间相互耦合,是一种强耦合的关系,做一个齿轮要考虑其他的齿轮怎么的设计参数,稍有偏差就会出现很大的误差。而电子手表中则是解耦成各个模块:显示、供电、计算模块等。各个模块可以单独开发,再通过通用的接口连接在一起。这就是一种解耦的思路。IOC相当于在各个类之间的连接器,实现将各个类的对象注入到其他类的对象中。
(1)强耦合的实例
例如在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。例如下面类 Human 中用到一个 Father 对象,我们就说类 Human 对类 Father 有一个依赖。
public class Human {
…
Father father;
…
public Human() {
father = new Father();
}
}
仔细看这段代码我们会发现存在一些问题:
1). 如果现在要改变 father 生成方式,如需要用new Father(String name)初始化 father,需要修改 Human 代码;
2). 如果想测试不同 Father 对象对 Human 的影响很困难,因为 father 的初始化被写死在了 Human 的构造函数中;
3). 如果new Father()过程非常缓慢,单测时我们希望用已经初始化好的 father 对象 Mock 掉这个过程也很困难。
(2)弱耦合的实例
依赖注入 上面将依赖在构造函数中直接初始化是一种 Hard初始化方式,弊端在于两个类不够独立,不方便测试。我们还有另外一种 Init 方式,如下:
public class Human {
…
Father father;
…
public Human(Father father) {
this.father = father;
}
}
上面代码中,我们将 father 对象作为构造函数的一个参数传入。在调用 Human 的构造方法之前外部就已经初始化好了 Father 对象。像这种非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注入。
现在我们发现上面 1 中存在的两个问题都很好解决了,简单的说依赖注入主要有两个好处:
1). 解耦,将依赖之间解耦。
2). 因为已经解耦,所以方便做单元测试,尤其是 Mock 测试。
(3)控制反转概念理解
软件系统在没有引入IOC容器之前,对象human依赖于对象father,那么对象human在初始化或者运行到某一点的时候,自己必须主动去创建对象father或者使用已经创建的对象father。无论是创建还是使用对象father,控制权都在自己手上。软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象human与对象father之间失去了直接联系,而是通过接口传入对象。相当于是把已经创建好的对象father通过接口注入human中,human对象失去了创建对象father的权利,反而是一种被动的接收别人创建好的对象,所以称为控制反转。也被称为依赖注入。