Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)

最近在学习Spring 框架,算是做点笔记记录一下吧!

搜索学习Spring框架,往往最多出现的就是IoC,因为IoC容器是Spring的核心。将从四个方面理解IoC

  • 什么是控制反转?
  • 什么是依赖注入?
  • 它们之间有什么关系
  • 如何在Spring 框架中使用依赖注入

控制反转(Inversion of  Controller)是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。

因为在传统的软件系统中,各个对象相互依赖,协同工作,互相耦合,只要其中一个不能工作,系统将受到严重的影响。可见下图1:

Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第1张图片

图1:软件中个对象之间的依赖(强耦合系统)

显然这种强耦合的系统对现在软件需求的发展是不利的,所以为了解决对象间耦合度过高的问题,软件专家Michael Mattson提出了IOC理论,用来实现对象之间的“解耦”。

解耦之后的软件系统,各对象之间通过一个“第三方”实现关联,使各个对象之间不存在耦合。全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心。

Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第2张图片

图2:IoC解耦过程

为什么叫“控制反转”呢?

  1. 软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
  2. 软件系统在引入IOC容器之后,这种情形就完全改变了,如图2所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。


依赖注入就是将实例变量传入到一个对象中去(Dependency Injection)

  • 什么是依赖?
            在Class A 中,有Class B 的实例,则称Class A 对Class B有一个依赖。例如在Human类中用到有Father类的实例father,即Human对类Father有一个依赖
                
             Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第3张图片
            这会存在什么问题呢?
  1. 如果改变father生产方式,例如使用new Father(String name)初始化father,则需要修改Human的代码
  2. 如果想测试不同的Father对象对Human的影响很困难,因为Human构造函数里已经写死了father的初始化
  3. 如果new Father()过程非常缓慢,单侧时我们希望用已经初始化好的father对象Mock掉这个过程很困难

  •    什么是注入?
               在Class A中讲Class B的实例对象作为构造函数的一个参数传入。例如如下
在调用Human的构造方法之前,外部就已经初始化好了Father对象。像这种非自己主动初始化依赖,而通过外部来的传入依赖的方式,就是 依赖注入
Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第4张图片

                  优点: 解耦,将依赖之间解耦,方便做单元测试 

  • IOC和DI的关系:IoC是一种思想,DI是一种实现方式
            IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,例如ServiceLocator

Spring中的依赖注入
Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第5张图片
创建两个类,都使用了依赖注入的方式,通过外部传入以来,而不是自己创建依赖。Spring IoC容器创建了finder并传给了MovieLister。可以使用xml配置IOC容器,也可以使用代码注解方式配置。
Spring学习——控制反转IoC和依赖注入DI的学习归纳(一)_第6张图片

每个bean代表一个对象的实例,默认是单例模式,即在程序的生命周期内,所有的对象都只有一个实例,进行重复使用。通过配置bean,IoC容器在启动的时候会根据配置生成bean。IoC容器会根据配置创建MovieFinder,在运行的时候把MovieFinder赋值给MovieLister的finder属性,完成以来注入的过程。


总结:
  • 控制反转是一种解耦合的思想,调用类只依赖接口,而不依赖具体的实现类,减少了耦合。控制权交给了容器,在运行的时候才由容器决定将具体的实现动态的“注入”到调用类的对象中。
  • 依赖注入是一种设计模式,可以作为控制反转的一种实现方式。依赖注入就是将实例变量传入到一个对象中去。
  • 通过IOC框架,类A依赖类B的强耦合关系可以在运行时通过容器建立,也就说把创建B实例的工作移交给容器,类A只管使用就可以了。

参考:http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/


你可能感兴趣的:(Spring)