架构师之路(39)---IoC框架

1 IoC理论的背景

    我们都知道,在採用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,全部的对象通过彼此的合作,终于实现系统的业务逻辑。

图1:软件系统中耦合的对象

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

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

图2:对象之间复杂的依赖关系

耦合关系不仅会出如今对象与对象之间,也会出如今软件系统的各模块之间,以及软件系统和硬件系统之间。怎样减少系统之间、模块之间和对象之间的耦合度,是软件project永远追求的目标之中的一个。为了解决对象之间的耦合度过高的问题,软件专家Michael Mattson提出了IOC理论,用来实现对象之间的“解耦”,眼下这个理论已经被成功地应用到实践其中,非常多的J2EE项目均採用了IOC框架产品Spring。

2 什么是控制反转(IoC)

IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。

1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。对于面向对象设计及编程的基本思想,前面我们已经讲了非常多了,不再赘述,简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而减少了解决这个问题的复杂度,并且能够灵活地被重用和扩展。IOC理论提出的观点大体是这种:借助于“第三方”实现具有依赖关系的对象之间的解耦,例如以下图:

图3:IOC解耦过程

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

我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:

图4:拿掉IoC容器后的系统

我们如今看到的画面,就是我们要实现整个系统所须要完毕的所有内容。这时候,A、B、C、D这4个对象之间已经没有了耦合关系,彼此毫无联系,这种话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经减少到了最低程度。所以,假设真能实现IOC容器,对于系统开发而言,这将是一件多么美好的事情,參与开发的每一成员仅仅要实现自己的类就能够了,跟别人没有不论什么关系!

我们再来看看,控制反转(IOC)究竟为什么要起这么个名字?我们来对照一下:

软件系统在没有引入IOC容器之前,如图1所看到的,对象A依赖于对象B,那么对象A在初始化或者执行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。不管是创建还是使用对象B,控制权都在自己手上。

软件系统在引入IOC容器之后,这样的情形就全然改变了,如图3所看到的,因为IOC容器的添?,对象A与对象B之间失去了直接联系,所以,当对象A执行到须要对象B的时候,IOC容器会主动创建一个对象B注入到对象A须要的地方。

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

3 IOC的别名:依赖注入(DI)

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

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

我们举一个生活中的样例,来帮助理解依赖注入的过程。大家对USB接口和USB设备应该都非常熟悉吧,USB为我们使用电脑提供了非常大的方便,如今有非常多的外部设备都支持USB接口。

图6:USB接口和USB设备

如今,我们利用电脑主机和USB接口来实现一个任务:从外部USB设备读取一个文件。

电脑主机读取文件的时候,它一点也不会关心USB接口上连接的是什么外部设备,并且它确实也无须知道。它的任务就是读取USB接口,挂接的外部设备仅仅要符合USB接口标准就可以。所以,假设我给电脑主机连接上一个U盘,那么主机就从U盘上读取文件;假设我给电脑主机连接上一个外置硬盘,那么电脑主机就从外置硬盘上读取文件。挂接外部设备的权力由我作主,即控制权归我,至于USB接口挂接的是什么设备,电脑主机是决定不了,它仅仅能被动的接受。电脑主机须要外部设备的时候,根本不用它告诉我,我就会主动帮它挂上它想要的外部设备,你看我的服务是多么的到位。这就是我们生活中常见的一个依赖注入的样例。在这个过程中,我就起到了IOC容器的作用。

通过这个样例,依赖注入的思路已经很清楚:当电脑主机读取文件的时候,我就把它所要依赖的外部设备,帮他挂接上。整个外部设备注入的过程和一个被依赖的对象在系统执行时被注入另外一个对象内部的过程全然一样。

我们把依赖注入应用到软件系统中,再来描写叙述一下这个过程:

对象A依赖于对象B,当对象 A须要用到对象B的时候,IOC容器就会马上创建一个对象B送给对象A。IOC容器就是一个对象制造工厂,你须要什么,它会给你送去,你直接使用即可了,而再也不用去关心你所用的东西是怎样制成的,也不用关心最后是怎么被销毁的,这一切所有由IOC容器包办。

在传统的实现中,由程序内部代码来控制组件之间的关系。我们常常使用newkeyword来实现两个组件之间关系的组合,这样的实现方式会造成组件之间耦合。IOC非常好地攻克了该问题,它将实现组件间关系从程序内部提到外部容器,也就是说由容器在执行期将组件间的某种依赖关系动态注入组件中。

  4 IOC为我们带来了什么优点

我们还是从USB的样例说起,使用USB外部设备比使用内置硬盘,究竟带来什么优点?

第一、USB设备作为电脑主机的外部设备,在插入主机之前,与电脑主机没有不论什么的关系,仅仅有被我们连接在一起之后,两者才发生联系,具有相关性。所以,不管两者中的不论什么一方出现什么的问题,都不会影响还有一方的执行。这样的特性体如今软件project中,就是可维护性比較好,很便于进行单元測试,便于调试程序和诊断故障。代码中的每个Class都能够单独測试,彼此之间互不影响,仅仅要保证自身的功能无误就可以,这就是组件之间低耦合或者无耦合带来的优点。

第二、USB设备和电脑主机的之间无关性,还带来了另外一个优点,生产USB设备的厂商和生产电脑主机的厂商全然能够是互不相干的人,各干各事,他们之间唯一须要遵守的就是USB接口标准。这样的特性体如今软件开发过程中,优点但是太大了。每一个开发团队的成员都仅仅须要关心实现自身的业务逻辑,全然不用去关心其他的人工作进展,由于你的任务跟别人没有不论什么关系,你的任务能够单独測试,你的任务也不用依赖于别人的组件,再也不用扯不清责任了。所以,在一个大中型项目中,团队成员分工明白、责任明晰,非常easy将一个大的任务划分为细小的任务,开发效率和产品质量必将得到大幅度的提高。

第三、同一个USB外部设备能够插接到不论什么支持USB的设备,能够插接到电脑主机,也能够插接到DV机,USB外部设备能够被重复利用。在软件project中,这样的特性就是可复用性好,我们能够把具有普遍性的经常使用组件独立出来,重复利用到项目中的其他部分,或者是其他项目,当然这也是面向对象的基本特征。显然,IOC不仅更好地贯彻了这个原则,提高了模块的可复用性。符合接口标准的实现,都能够插接到支持此标准的模块中。

第四、同USB外部设备一样,模块具有热插拔特性。IOC生成对象的方式转为外置方式,也就是把对象生成放在配置文件中进行定义,这样,当我们更换一个实现子类将会变得非常easy,仅仅要改动配置文件就能够了,全然具有热插拨的特性。

以上几点优点,难道还不足以打动我们,让我们在项目开发过程中使用IOC框架吗?

5 IOC容器的技术剖析

IOC中最主要的技术就是“反射(Reflection)”编程,眼下.Net C#、Java和PHP5等语言均支持,当中PHP5的技术书籍中,有时候也被翻译成“映射”。有关反射的概念和使用方法,大家应该都非常清楚,通俗来讲就是依据给出的类名(字符串方式)来动态地生成对象。这样的编程方式能够让对象在生成时才决定究竟是哪一种对象。反射的应用是非常广泛的,非常多的成熟的框架,比方象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做为最主要的技术手段。

反射技术事实上非常早就出现了,但一直被忽略,没有被进一步的利用。当时的反射编程方式相对于正常的对象生成方式要慢至少得10倍。如今的反射技术经过改良优化,已经非常成熟,反射方式生成对象和通常对象生成方式,速度已经相差不大了,大约为1-2倍的差距。

我们能够把IOC容器的工作模式看做是工厂模式的升华,能够把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件里给出定义,然后利用编程语言的的反射编程,依据配置文件里给出的类名生成对应的对象。从实现来看,IOC是把曾经在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

6 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已经被逐渐应用于各种项目中。

7 使用IOC框架应该注意什么

使用IOC框架产品可以给我们的开发过程带来非常大的优点,可是也要充分认识引入IOC框架的缺点,做到心中有数,杜绝滥用框架。

第一、软件系统中因为引入了第三方IOC容器,生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续,所以,我们在刚開始使用IOC框架的时候,会感觉系统变得不太直观。所以,引入了一个全新的框架,就会添加?团队成员学习和认识的培训成本,而且在以后的执行维护中,还得让新添?者具备相同的知识体系。

第二、因为IOC容器生成对象是通过反射方式,在执行效率上有一定的损耗。假设你要追求执行效率的话,就必须对此进行权衡。

第三、详细到IOC框架产品(比方:Spring)来讲,须要进行大量的配制工作,比較繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。

第四、IOC框架产品本身的成熟度须要进行评估,假设引入一个不成熟的IOC框架产品,那么会影响到整个项目,所以这也是一个隐性的风险。

我们大体能够得出这种结论:一些工作量不大的项目或者产品,不太适合使用IOC框架产品。另外,假设团队成员的知识能力欠缺,对于IOC框架产品缺乏深入的理解,也不要贸然引入。最后,特别强调执行效率的项目或者产品,也不太适合引入IOC框架产品,象WEB2.0站点就是这种情况。

时间: 2024-10-11 04:47:42

架构师之路(39)---IoC框架的相关文章

java架构师之路:JAVA程序员必看的15本书的电子版下载地

转自:http://www.shangxueba.com/faq/view376.html 作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水平的Java程序员们. 一.Java编程入门类 对于没有Java编程经验的程序员要入门,随便读什么入门书籍都一样,这个阶段需要你快速的掌握Java基础语法和基本用法,宗旨就是“囫囵吞枣不求甚解”,先对Java

测试专家讲述通往测试架构师之路

随着对测试这个职业的了解越来越深,对微软测试技术的掌握越来越多,慢慢地,人就开始对那些测试“大牛”在做什么感兴趣了.他们就是那些在公司内部挂着“测试架构师”头衔的一小撮人. AD: WOT2014:用户标签系统与用户数据化运营培训专场 在公司呆了有几个年头了.在测试技术方面的技能长进了不少,又能享受写代码的乐趣,同事们经常交流对软件测试技术的见解,也在项目中实现一些创新的测试技术和基于自己的想法设计好的测试框架,每天过的很开心.随着对测试这个职业的了解越来越深,对微软测试技术的掌握越来越多,慢慢

深入大数据架构师之路,问鼎40万年薪视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

Java架构师之路:从Java码农到年薪八十万的架构师,最牛Java架构师进阶路线

从Java码农到年薪八十万的架构师,资深架构师大牛给予Java技术提升学习路线建议,如何成为一名资深Java架构师? 对于工作多年的程序员而言,日后的职业发展无非是继续专精技术.转型管理和晋升架构师三种选择.架构师在一家公司有多重要.优秀架构师需要具备怎样的素质以及架构师的发展现状三个方面来分析 程序员如何才能晋升为优秀的高薪架构师? 希望通过本文让程序员们了解架构师的市场行情,了解架构师的发展前景,并帮助你更清晰地做出职业规划. 架构师在一家公司有多重要 架构师在公司中担当着「IT架构灵魂人物

架构师之路虽难,但不要放弃!

由于昨天深夜学习不在状态,问责自己的话,分享给那些一直坚持这条道路而又有感到迷茫的小伙伴们! 致深夜迷茫的自己:    北京的压力真的很大吗?你自己的压力真的就那么大吗?真的很累吗?难道想放弃了?心甘情愿的去做一个平庸的人吗?还记不记得当初有那么多瞧不起你的眼神,难道你忘了吗?你知道吗,在你的老师眼里你是个很有能力的学生,每个老师都愿意把最高的分数给你,这是为什么?因为那时候你有一颗战无不胜.不服输的心!现在是怎么了,学不进去了吗?累?熬不下去了?刚刚接手公司中心服务器集群,就感觉累了?你知道吗

Android架构师之路-架构师的决策

android架构师之路-架构师的决策 内涵+造型:可能大部分人对这个内涵和造型不是很理解,在这里我可以给大家举个生动的例子:相信很多人都有自己的汽车, 我们总结汽车有哪些属性和功能,这些都是内涵,大自然中的每个对象都有自己的内涵(人有手有脚,还可以跑),然后我们 将这些内涵放入指定的造型中,类似模版,比如java语言如果定义一个class的时候,必须在作用域(大括号内部)指定属性和 函数,这个class的定义规范就是一个造型,然后我们将汽车这个内涵按照class的规范定义一个汽车class,那

2015重磅炸弹——【视频】Android从程序员到架构师之路

眼看2015年一月份就要接近尾声了,今年的开年第一颗炸弹也该引爆了! Android从程序员到架构师之路,高焕堂老师主讲,总共234节课. 为了方便大家观看,直接传了MP4格式的视频文件,不想下载的朋友可以在线观看. 链接: http://pan.baidu.com/s/1qW1B9mO 密码: sf79 望支持,谢谢!

[Android]Android从程序员到架构师之路的一些笔记

高焕堂老师的讲得不错 //EIT造型 E基类   I接口    T(基类的子类)实现接口 [Android]Android从程序员到架构师之路的一些笔记

2018年给自己运维架构师之路总结(半年)

一转眼2018年已过去一半,现在很多高大上的技术不断涌现而出,不过我一直都相信,根基不牢,地动山摇,所有希望我自己能坚持自己的初心,不要心浮气躁,谈事下来,一步步走向我的架构师之路. 下面就来总结一下我的工作内容: 传送门:https://aonaotu.com/open/5b236fa7dae7f00014b22c83 原文地址:http://blog.51cto.com/qiuyt/2129941