AP计算机科学A(APcomputer science A)复习备考攻略视频教程
43754 人在学
学习Java框架的同学都会听过IOC,但是对于刚刚接触的朋友来说,可能并不太了解什么是IOC?在这里要说的是,在学习IOC之前你要明白的是IOC并不是一种技术而是一种思想。接下来本文会对IOC的理论、IOC的优缺点以及它为什么称控制反转作简单的介绍。
IOC理论
如果你打开机械手表的后盖,想一些精细一些的机械手表你会看到若干个齿轮在带动时针、分针以及秒针的运行。就如图中的所描述的,在一个齿轮组中,由这些独立的齿轮相互合在一起,协同工作,共同完成某项任务。但是一旦一个齿轮出现了问题就会波及整个齿轮组。
而我们所知道的面向对象设计的软件系统中,它的底层就像齿轮组一样由若干个对象构成的,各个对象通过相互之间的合作,最终实现系统的业务逻辑。齿轮组中的齿轮间的啮合关系,和面向对象设计的软件系统中的对象之间的耦合非常相似。在软件系统中的耦合关系是无可避免的,这是协同工作的基础。耦合关系不仅仅只出现在对象于对象之间,也会出现在软件系统的模块之间,以及软硬件系统之间。而软件工程永远追求的目标是降低这些对象、模块、系统之间的耦合度。
并且随着工业级应用的不断发展,系统中对象之间的依赖关系越来越复杂,经常会出现多重依赖性的关系。所以对于系统的分析和设计面临着更大的挑战和考验。不然对象耦合度太高的系统必定会出现牵一发而动全身的现象。
所以为了解决高耦合度的问题,在1996年软件专家Michael Mattson提出了IOC理论用于实现对象之间的“解耦”并且成功的应用到了实践中。
什么是IOC?(控制反转)
IoC是Inversion of Control的缩写,有的翻译成“控制反转”,还有翻译成为“控制反向”或者“控制倒置”。它不是一种技术,而是一种思想。在java的开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
软件专家Michael Mattson在1996年首先在一篇有关探讨面向对象框架的文章中提出了IOC这个概念。简单来说就是把复杂的系统分解成可以相互合作的对象,在这些对象进行封装之后,就实现内部对外部的透明,这样就解决了问题的复杂程度。
IOC的理论观点如图:
图中表达的意思是,在把各个对象类进行封装之后,通过IOC容器来关联这些对象类。这样子对象与对象之间就是通过IOC进行联系,从而减少了对象与对象的直接关系。
但是如果去掉了IOC容器之后对象与对象之间又会有了直接的关系。如图:
为什么叫控制反转?
谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
我们可以进行对比:
— 软件系统在没有引入IoC容器之前,对象A依赖对象B,那么A对象在实例化或者运行到某一点的时候,自己必须主动创建对象B或者使用已经创建好的对象B,其中不管是创建还是使用已创建的对象B,控制权都在我们自己手上。
— 如果软件系统引入了Ioc容器之后,对象A和对象B之间失去了直接联系,所以,当对象A实例化和运行时,如果需要对象B的话,IoC容器会主动创建一个对象B注入到对象A所需要的地方。
— 通过前面的对比,可以看到对象A获得依赖对象B的过程,由主动行为变成了被动行为,即把创建对象交给了IoC容器处理,控制权颠倒过来了,这就是控制反转。
IOC也可以叫做依赖注入(DI)
在2004年的时候,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”上文我们已经解释过了,得出的答案就是“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
也就可以说,IOC和DI只是从不同的角度去描述同一件事情。通过引入IOC容器利用依赖关系注入实现对象之间的解耦。由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IOC 而言,“依赖注入”明确描述了“被注入对象依赖IOC容器配置依赖对象”。
IOC的优点以及缺点
灵活性
可以简单的改变一个广泛使用的接口的实现类
改变检索策略对于一个给定的类更简单(例如移动服务从类路径的JNDI树)
在一个地方调价拦截器是简单的(如添加一个拦截器与基于jdbc的缓存DAO)
可读性
这些项目有一个统一的组件模型,而不是零散的。
代码更加简单。
可测试性
当他们通过构造函数的时候依赖关系很容易取代。
可维护性比较好并且便于进行单元测试
更多的测试会导致更高的代码质量
虽然说使用IOC容器可以给我们的开发带来很多的好处,但是也要知道IOC框架的缺点。
1.由于软件系统中引入了IOC容器,会使得生成对象的步骤变得复杂,因为本来只是两者之间的事情现在又多了一道程序。
2.因为IOC容器生成对象是通过反射的方式,所以在运行效率上有一定的的减少。
3.对于IOC框架产品来说,需要大量的配置工作,比较麻烦。
4.如果引入一个不成熟的IOC框架产品有可能会影响到整个项目的运行,这是IOC中一个隐藏的风险。
IOC容器技术
在IOC中最基本的技术就是“反射”。关于反射的概念,简单来说就是根据给出的类名来动态的生成对象。这种编程方式可以让对象决定到底是哪一种对象。目前.NET C#、Java和php5等语言均支持,很多的成熟的框架,比如象Java中的Hibernate、spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做为最基本的技术手段。
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已经被广泛应用于各种项目中。
刚刚学习的朋友可能对与IOC和DI两个概念分不清,在本文中简单的介绍了一下两者以及之间的联系。如果有需要详细了解的朋友可以去网上查找。总的来说IOC框架的作用还有很好的,特别是对于大型的软件系统之中。希望本文能对有所疑问的朋友有所帮助。