●为何是反转, 哪些方面反转了: 有反转就有正转, 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象, 也就是正转; 而反转则是由容器来帮忙创建及注入依赖对象; 为何是反转? 因为由容器帮我们查找及注入依赖对象, 对象只是被动的接受依赖对象, 所以是反转; 哪些方面反转了? 依赖对象的获取被反转了.
用图例说明一下, 传统程序设计如图 2-1, 都是主动去创建相关对象然后再组合起来:
图 1-1 传统应用程序示意图
当有了 IoC/DI 的容器后, 在客户端类中不再主动去创建这些对象了, 如图 2-2 所示:
图 1-2 有 IoC/DI 容器后程序结构示意图
1.2,IoC 能做什么
IoC 不是一种技术, 只是一种思想, 一个重要的面向对象编程的法则, 它能指导我们如何设计出松耦合, 更优良的程序. 传统应用程序都是由我们在类内部主动创建依赖对象, 从而导致类与类之间高耦合, 难于测试; 有了 IoC 容器后, 把创建和查找依赖对象的控制权交给了容器, 由容器进行注入组合对象, 所以对象与对象之间是 松散耦合, 这样也方便测试, 利于功能复用, 更重要的是使得程序的整个体系结构变得非常灵活.
其实 IoC 对编程带来的最大改变不是从代码上, 而是从思想上, 发生了 "主从换位" 的变化. 应用程序原本是老大, 要获取什么资源都是主动出击, 但是在 IoC/DI 思想中, 应用程序就变成被动的了, 被动的等待 IoC 容器来创建并注入它所需要的资源了.
IoC 很好的体现了面向对象设计法则之一 -- 好莱坞法则:"别找我们, 我们找你"; 即由 IoC 容器帮对象找相应的依赖对象并注入, 而不是由对象主动去找.
1.3,IoC 和 DI
DI-Dependency Injection, 即 "依赖注入": 组件之间依赖关系由容器在运行期决定, 形象的说, 即由容器动态的将某个依赖关系注入到组件之中. 依赖注入的目的并非为软件系统带来更多功能, 而是为了提升组件重用的频率, 并为系统搭建一个灵活, 可扩展的平台. 通过依赖注入机制, 我们只需要通过简单的配置, 而无需任何代码就可指定目标需要的资源, 完成自身的业务逻辑, 而不需要关心具体的资源来自何处, 由谁实现.
理解 DI 的关键是:"谁依赖谁, 为什么需要依赖, 谁注入谁, 注入了什么", 那我们来深入分析一下:
●谁依赖于谁: 当然是应用程序依赖于 IoC 容器;
●为什么需要依赖: 应用程序需要 IoC 容器来提供对象需要的外部资源;
●谁注入谁: 很明显是 IoC 容器注入应用程序某个对象, 应用程序依赖的对象;
●注入了什么: 就是注入某个对象所需要的外部资源 (包括对象, 资源, 常量数据).
IoC 和 DI 由什么关系呢? 其实它们是同一个概念的不同角度描述, 由于控制反转概念比较含糊 (可能只是理解为容器控制对象这一个层面, 很难让人想到谁来维护对象关系), 所以 2004 年大师级人物 Martin Fowler 又给出了一个新的名字:"依赖注入", 相对 IoC 而言,"依赖注入" 明确描述了 "被注入对象依赖 IoC 容器配置依赖对象".
看过很多对 Spring 的 IoC 理解的文章, 好多人对 IoC 和 DI 的解释都晦涩难懂, 反正就是一种说不清, 道不明的感觉, 读完之后依然是一头雾水, 感觉就是开涛这位技术牛人写得特别通俗易懂, 他清楚地解释了 IoC(控制反转) 和 DI(依赖注入) 中的每一个字, 读完之后给人一种豁然开朗的感觉. 我相信对于初学 Spring 框架的人对 IoC 的理解应该是有很大帮助的.
二, 分享 Bromon 的 blog 上对 IoC 与 DI 浅显易懂的讲解 2.1,IoC(控制反转)
首先想说说 IoC(Inversion of Control, 控制反转). 这是 spring 的核心, 贯穿始终. 所谓 IoC, 对于 spring 框架来说, 就是由 spring 来负责控制对象的生命周期和对象间的关系. 这是什么意思呢, 举个简单的例子, 我们是如何找女朋友的? 常见的情况是, 我们到处去看哪里有长得漂亮身材又好的 mm, 然后打听她们的兴趣爱好, qq 号, 电话号, ip 号, iq 号........., 想办法认识她们, 投其所好送其所要, 然后嘿嘿...... 这个过程是复杂深奥的, 我们必须自己设计和面对每个环节. 传统的程序开发也是如此, 在一个对象中, 如果要使用另外的对象, 就必须得到它 (自己 new 一个, 或者从 JNDI 中查询一个), 使用完之后还要将对象销毁 (比如 Connection 等), 对象始终会和其他的接口或类藕合起来.
那么 IoC 是如何做的呢? 有点像通过婚介找女朋友, 在我和女朋友之间引入了一个第三者: 婚姻介绍所. 婚介管理了很多男男女女的资料, 我可以向婚介提出一个列表, 告诉它我想找个什么样的女朋友, 比如长得像李嘉欣, 身材像林熙雷, 唱歌像周杰伦, 速度像卡洛斯, 技术像齐达内之类的, 然后婚介就会按照我们的要求, 提供一个 mm, 我们只需要去和她谈恋爱, 结婚就行了. 简单明了, 如果婚介给我们的人选不符合要求, 我们就会抛出异常. 整个过程不再由我自己控制, 而是有婚介这样一个类似容器的机构来控制. Spring 所倡导的开发方式就是如此, 所有的类都会在 spring 容器中登记, 告诉 spring 你是个什么东西, 你需要什么东西, 然后 spring 会在系统运行到适当的时候, 把你要的东西主动给你, 同时也把你交给其他需要你的东西. 所有的类的创建, 销毁都由 spring 来控制, 也就是说控制对象生存周期的不再是引用它的对象, 而是 spring. 对于某个具体的对象而言, 以前是它控制其他对象, 现在是所有对象都被 spring 控制, 所以这叫控制反转.
2.2,DI(依赖注入)
IoC 的一个重点是在系统运行中, 动态的向某个对象提供它所需要的其他对象. 这一点是通过 DI(Dependency Injection, 依赖注入) 来实现的. 比如对象 A 需要操作数据库, 以前我们总是要在 A 中自己编写代码来获得一个 Connection 对象, 有了 spring 我们就只需要告诉 spring,A 中需要一个 Connection, 至于这个 Connection 怎么构造, 何时构造, A 不需要知道. 在系统运行时, spring 会在适当的时候制造一个 Connection, 然后像打针一样, 注射到 A 当中, 这样就完成了对各个对象之间关系的控制. A 需要依赖 Connection 才能正常运行, 而这个 Connection 是由 spring 注入到 A 中的, 依赖注入的名字就这么来的. 那么 DI 是如何实现的呢? Java 1.3 之后一个重要特征是反射 (reflection), 它允许程序在运行的时候动态的生成对象, 执行对象的方法, 改变对象的属性, spring 就是通过反射来实现注入的.
理解了 IoC 和 DI 的概念后, 一切都将变得简单明了, 剩下的工作只是在 spring 的框架中堆积木而已.
三, 我对 IoC(控制反转) 和 DI(依赖注入) 的理解
在平时的 java 应用开发中, 我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成, 在没有使用 Spring 的时候, 每个对象在需要使用他的合作对象时, 自己均要使用像 new object() 这样的语法来将合作对象创建出来, 这个合作对象是由自己主动创建出来的, 创建合作对象的主动权在自己手上, 自己需要哪个合作对象, 就主动去创建, 创建合作对象的主动权和创建时机是由自己把控的, 而这样就会使得对象间的耦合度高了, A 对象需要使用合作对象 B 来共同完成一件事, A 要使用 B, 那么 A 就对 B 产生了依赖, 也就是 A 和 B 之间存在一种耦合关系, 并且是紧密耦合在一起, 而使用了 Spring 之后就不一样了, 创建合作对象 B 的工作是由 Spring 来做的, Spring 创建好 B 对象, 然后存储到一个容器里面, 当 A 对象需要使用 B 对象时, Spring 就从存放对象的那个容器里面取出 A 要使用的那个 B 对象, 然后交给 A 对象使用, 至于 Spring 是如何创建那个对象, 以及什么时候创建好对象的, A 对象不需要关心这些细节问题 (你是什么时候生的, 怎么生出来的我可不关心, 能帮我干活就行),A 得到 Spring 给我们的对象之后, 两个人一起协作完成要完成的工作即可.
所以控制反转 IoC(Inversion of Control) 是说创建对象的控制权进行转移, 以前创建对象的主动权和创建时机是由自己把控的, 而现在这种权力转移到第三方, 比如转移交给了 IoC 容器, 它就是一个专门用来创建对象的工厂, 你要什么对象, 它就给你什么对象, 有了 IoC 容器, 依赖关系就变了, 原先的依赖关系就没了, 它们都依赖 IoC 容器了, 通过 IoC 容器来建立它们之间的关系.
这是我对 Spring 的 IoC(控制反转) 的理解. DI(依赖注入) 其实就是 IoC 的另外一种说法, DI 是由 Martin Fowler 在 2004 年初的一篇论文中首次提出的. 他总结: 控制的什么被反转了? 就是: 获得依赖对象的方式反转了.
四, 小结
对于 Spring IoC 这个核心概念, 我相信每一个学习 Spring 的人都会有自己的理解. 这种概念上的理解没有绝对的标准答案, 仁者见仁智者见智. 如果有理解不到位或者理解错的地方, 欢迎广大园友指正!
转至: http://m.sohu.com/a/204558803_488150
来源: http://www.bubuko.com/infodetail-3066423.html