【Spring】IOC
浅谈IOC
IOC的理论背景
图1:传统系统中,对象之间相互引用的一幅图,在采用面向对象方法设计的软件系统中,它的底层的实现都是由n个对象所组成的,所有的对象通彼此之间的合作最终实现系统的业务逻辑,如果我们打开机械式手表的后盖,我们就会看到与图1类似的清形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。这些齿轮相互耦合在一起,共同完成某项任务。在这样的齿轮组中,如果有一个齿轮出现一个问题,可能会影响到整个齿轮组的正常运转,齿轮组齿轮间的耦合关系与软件系统中对象之间的耦合关系非常相似。随着系统规模变大,对象之间依赖关系越来越复杂,架构师和设计师对系统的设计和分析面临更大的挑战,对象之间的耦合度过高的系统,必然会出现牵一发而动全身的情形,降低系统之间、模块之间、对象之间的耦合度是软件工程追求的目标。IOC理论的提出,就是为了解决对象之间耦合度过高的问题,实现对象之间的解耦。
图2 解耦的过程
IOC理论提出的观点大致是这样的:借助于第三方来实现对具有依赖关系的对象之间的解耦,对象之间没有了耦合关系。由于引进了第三方IOC容器,使得对象A、B、C、D之间没有了耦合关系,齿轮之间的传动全部依靠了第三方,全部对象的控制权全部交给了第三方IOC容器,IOC容器成了整个系统的关键核心,它起到了一种凝合剂i的作用,把系统中的所有对象凝合在一起发挥作用。
图3 理想的系统
这四个对象之间彼此毫无联系,这样在实现A的时候,无需去考虑B、C、和D,对象之间的依赖关系降低到了最低程度。 参与开发的每一位成员,只要实现自己的类就好了,跟别人没有任何关系。我们再来看看,控制反转到底为什么取这个名字。
软件系统在没有引入IOC容器之前,就像图1所示,对象A 依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须去创建对象B,或者是使用已经创建的B,无论是创建还是使用对象B,控制权全部都在自己手上,在软件系统引入了IOC以后,这种情形就完全改变了,如图2所示,由于IOC容器的加入,对象A和对象B失去了直接的联系,所以当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B,注入到对象A所需要的地方,通过前后的对比,不然看出,对象A获得依赖对象B的过程, 由主动行为变为了被动行为,控制权颠倒过来了,这个就是控制反转的名称的由来。哪些东西被反转了?获得依赖对象的过程被反转。获得依赖对象的过程由自身的管理变为了由IOC容器主动的注入。依赖注入(DI)其实是实现控制反转(IOC)的方式。
依赖注入DI
IOC的另外的名字叫做依赖注入(DI),所谓的依赖注入,就是由IOC容器再运行期间动态地将某种依赖注入到对象之中。所以,依赖注入(DI)和控制反转(IOC)是从不容的角度描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
图4 电脑 和 外设都是对象,人起到IOC容器的作用
IOC容器就像一个对象制造工厂,你需要什么,它就会传送给你。你直接使用就可以,再也不用关心你是用的东西是如何生成的,最后如何销毁的,这一切都有IOC容器管理。再传统的实现中, 由程序内部代码来控制组件之间的关系,我们经常使用new关键字来实现两个组件之间关系的组合,这种方式会造成组件之间耦合,IOC很好的解决了这种问题,它将 实现组件间的关系 从程序内部提炼到了外部容器,也就是说由容器再运行期间将组件间的某种依赖关系动态地注入到组件中。
IOC好处
IOC在编程过程中不会对业务对象构成很强的侵入性,使用IOC之后,对象具有更好的可实行性,可重用性和可扩展性:
- 降低组件之间的耦合度
- 提高开发效率和产品质量
- 同意标准,提高模块的复用性
- 模块具有热插拔特性
举个例子:使用USB外部设备比使用电脑内置硬盘带来什么好处呢?第一:USB设备在插入主机之前,与电脑主机没有任何关系,只有被连接在一起后,才有关系,所以无论任何一方发生问题,都不会影响另一方,这在软件工程中就叫做可维护性,非常便于单元测试、调试程序和诊断故障。代码中的每个class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可,这就是组件之间低耦合、无耦合带来的好处。 第二 USB和主机之间的无关性还带来了另外一个好处,生产USB和生产电脑的厂商可以是完全互不相干的两个人,他们各干各事,唯一需要遵守的是USB接口的标准,这种特性体现在软件开发过程中,好处很大,每一个开发团队的成员都只需要关心实现自身的业务逻辑,完全不用关心其他人的工作进度。你的任务可以单独测试也不依赖于别人的组件,每个人分工明确,效率提高。第三:提高了模块的复用性。同一个USB外部设备,可以插到任何支持USB的设备,可以插到电脑主机,可以插到DV机,USB外部设备可以被反复利用。我们可以把具有普遍性的、常用的组件独立出来,反复利用到项目中的其他部分或者其他项目,当然这也是面向对象的基本特征。第四:模块具有热插拔特性。IOC生成对象的方式,转为外置方式,也就是把对象生成放到了配置文件进行定义,这样当我们更换一个实现子类将会变得更加简单,只要修改配置文件就可以,完全具有热插拔的特性。(热插拔(hot-plugging或Hot Swap)即带电插拔,热插拔功能就是允许用户在不关闭系统,不切断电源的情况下取出和更换损坏的硬盘、电源或板卡等部件,从而提高了系统对灾难的及时恢复能力、扩展性和灵活性等,例如一些面向高端应用的磁盘镜像系统都可以提供磁盘的热插拔功能。)
IOC的通俗理解如下
- IOC控制反转:说的是创建对象实例的控制权从代码控制剥离到IOC容器控制,实际就是你在XML文件当中的控制,侧重于原理
- DI依赖注入:说的是再创建对象实例时,为这个对象注入属性值或其他对象实例,它侧重于实现。