SSM框架--IOC的原理

IOC 是 Inversion of Control 的缩写,它把复杂系统分解成相互合作的对象,借助于 “第三方” 实现具有依赖关系的对象之间的解耦

IOC理论背景


如果我们打开机械式手表的后盖,就会看到与上面类似的情形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。它拥有多个独立的齿轮,这些齿轮相互啮合在一起,协同工作,共同完成某项任务。我们可以看到,在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转。

齿轮组中齿轮之间的啮合关系, 与软件系统中对象之间的耦合关系非常相似。对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。现在,伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。


IOC概念


IOC 是 Inversion of Control 的缩写,多数书籍翻译成 “控制反转”,还有些书籍翻译成为“控制反向” 或者“控制倒置”。
1996 年,Michael Mattson 在一篇有关探讨面向对象框架的文章中,首先提出了 IOC 这个概念。**简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。**IOC 理论提出的观点大体是这样的:借助于 “第三方” 实现具有依赖关系的对象之间的解耦,如下图:

由于引进了中间位置的 “第三方”,也就是 IOC 容器,使得 A、B、C、D 这 4 个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方” 了,全部对象的控制权全部上缴给 “第三方”IOC 容器,所以,IOC 容器成了整个系统的关键核心,它起到了一种类似“粘合剂” 的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个 “粘合剂”,对象与对象之间会彼此失去联系,这就是有人把 IOC 容器比喻成“粘合剂” 的由来。
把上图中间的 IOC 容器拿掉,然后再来看看这套系统:

我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,A、B、C、D 这 4 个对象之间已经没有了耦合关系,彼此毫无联系,这样的话,当你在实现 A 的时候,根本无须再去考虑 B、C 和 D 了,对象之间的依赖关系已经降低到了最低程度。
我们再来看看,控制反转 (IOC) 到底为什么要起这么个名字?我们来对比一下:

  • 软件系统在没有引入 IOC 容器之前,如图 1 所示,对象 A 依赖于对象 B,那么对象 A 在初始化或者运行到某一点的时候,自己必须主动去创建对象 B 或者使用已经创建的对象 B。无论是创建还是使用对象 B,控制权都在自己手上。
  • 软件系统在引入 IOC 容器之后,这种情形就完全改变了,如图 3 所示,由于 IOC 容器的加入,对象 A 与对象 B 之间失去了直接联系,所以,当对象 A 运行到需要对象 B 的时候,IOC 容器会主动创建一个对象 B 注入到对象 A 需要的地方。
  • 通过前后的对比,我们不难看出来:对象 A 获得依赖对象 B 的过程, 由主动行为变为了被动行为,控制权颠倒过来了,这就是 “控制反转” 这个名称的由来。

DI概念(依赖注入)


2004 年,Martin Fowler 探讨了同一个问题,既然 IOC 是控制反转,那么到底是 “哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由 IOC 容器主动注入。于是,他给“控制反转” 取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现 IOC 的方法:注入。所谓依赖注入,就是由 IOC 容器在运行期间,动态地将某种依赖关系注入到对象之中。

所以,依赖注入 (DI) 和控制反转 (IOC) 是从不同的角度的描述的同一件事情,就是指通过引入 IOC 容器,利用依赖关系注入的方式,实现对象之间的解耦


DI应用过程


  • 对象 A 依赖于对象 B, 当对象 A 需要用到对象 B 的时候,IOC 容器就会立即创建一个对象 B 送给对象 A。IOC 容器就是一个对象制造工厂,你需要什么,它会给你送去,你直接使用就行了,而再也不用去关心你所用的东西是如何制成的,也不用关心最后是怎么被销毁的,这一切全部由 IOC 容器包办。
  • 在传统的实现中,由程序内部代码来控制组件之间的关系。我们经常使用 new 关键字来实现两个组件之间关系的组合,这种实现方式会造成组件之间耦合。IOC 很好地解决了该问题,它将实现组件间关系从程序内部提到外部容器,也就是说由容器在运行期将组件间的某种依赖关系动态注入组件中。

简单来说:

  • 这个容器可以自动对你的代码进行初始化,你只需要维护一个 Configuration(可以是 xml 可以是一段代码),而不用每次初始化一辆车都要亲手去写那一大段初始化的代码
  • 我们在创建实例的时候不需要了解其中的细节

IOC容器的技术剖析和产品


IOC 容器的技术剖析

IOC 中最基本的技术就是 “反射(Reflection)” 编程,目前. Net C#、Java 和 PHP5 等语言均支持,其中 PHP5 的技术书籍中,有时候也被翻译成 “映射”。有关反射的概念和用法,大家应该都很清楚,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象。这种编程方式可以让对象在生成时才决定到底是哪一种对象。反射的应用是很广泛的,很多的成熟的框架,比如象 Java 中的 Hibernate、Spring 框架,.Net 中 NHibernate、Spring.Net 框架都是把 “反射” 做为最基本的技术手段。
反射技术其实很早就出现了,但一直被忽略,没有被进一步的利用。当时的反射编程方式相对于正常的对象生成方式要慢至少得 10 倍。现在的反射技术经过改良优化,已经非常成熟,反射方式生成对象和通常对象生成方式,速度已经相差不大了,大约为 1-2 倍的差距。
我们可以把 IOC 容器的工作模式看做是工厂模式的升华,可以把 IOC 容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC 是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

IOC 容器的一些产品

Sun ONE 技术体系下的 IOC 容器有:轻量级的有 Spring、Guice、Pico Container、Avalon、HiveMind;重量级的有 EJB;不轻不重的有 JBoss,Jdon 等等。Spring 框架作为 Java 开发中 SSH(Struts、Spring、Hibernate) 三剑客之一,大中小项目中都有使用,非常成熟,应用广泛,EJB 在关键性的工业级项目中也被使用,比如某些电信业务。
.Net 技术体系下的 IOC 容器有:Spring.Net、Castle 等等。Spring.Net 是从 Java 的 Spring 移植过来的 IOC 容器,Castle 的 IOC 容器就是 Windsor 部分。它们均是轻量级的框架,比较成熟,其中 Spring.Net 已经被逐渐应用于各种项目中。

0%