Skip to main content

Java 控制反转(IoC)和依赖注入(DI)

· 10 min read
Zeffon Wu

控制反转依赖注入的概念可能有些抽象,我细想一下以往的开发过程中,也是不知道它们实际的用途是什么,对它们的理解也是仅仅有个模糊的影子而已。对此再次提及它们时,我不能再对此视而不见了。所以在网上查阅一些资料,包括一些大神写的博客,希望自己能在这次有比较有好的认识。如果有理解不到位或者理解错的地方,望大家多多指正。

前言

控制反转依赖注入的概念可能有些抽象,我细想一下以往的开发过程中,也是不知道它们实际的用途是什么,对它们的理解也是仅仅有个模糊的影子而已。对此再次提及它们时,我不能再对此视而不见了。所以在网上查阅一些资料,包括一些大神写的博客,希望自己能在这次有比较有好的认识。如果有理解不到位或者理解错的地方,望大家多多指正。

正文

控制反转 IoC

首先,我们先明白什么是 IoC?在 Java 开发中,IoC 是意味着将你设计好的对象交给了IoC 容器进行控制,而不再是传统的在你的对象内部进行控制。所谓的控制反转就是要去反转控制权。而理解好 IoC 需要明白在这控制中,谁控制谁,控制着什么?为什么是反转呢?还有哪些方面的控制被反转了?

谁控制谁,控制什么?

在传统的面向对象编程设计,我们需要直接在对象内部通过 new 的方式进行创建对象,这种属于是程序主动去创建依赖对象;而 IoC 是有专门一个容器来创建这些对象,即由Ioc 容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取。 传统的面向对象编程设计

java-IoC-and-DI-01.png

IoC容器

java-IoC-and-DI-02.png

为什么是反转呢?

有反转就有正转。在传统的面向对象编程设计中是由我们自己在对象中主动控制去直接 new 来获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象。为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转。

哪些方面的控制被反转了?

依赖对象的获取被反转了。原本是houseService 对象需要主动获取houseDao 对象的,现在变成houseDao 对象注入到houseService 对象中。houseService 对象不需要创建什么,IoC 容器会帮它查找并注入依赖对象houseDao 对象

IoC 的好处

  1. IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。在单一职责原则的设计下,很少有单独一个对象就能完成的任务。大多数任务都需要复数的对象来协作完成,这样对象与对象之间就有了依赖。一开始对象之间的依赖关系是自己解决的,需要什么对象了就New一个出来用,控制权是在对象本身。但是这样耦合度就非常高,可能某个对象的一点小修改就会引起连锁反应,需要把依赖的对象一路修改过去。
  2. 这样会导致代码高度和并且难以维护和调试。为了避免这种情况,需要将对象内部的控制权反转到外部(IoC 容器)。有了 IoC 容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
  3. 其实 IoC 对编程带来的最大改变不是从代码上,而是从思想上,发生了主从换位的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

IoC 和 DI

  • DI—Dependency Injection,即依赖注入:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解 DI 的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  1. 谁依赖于谁:当然是应用程序依赖于 IoC 容器;
  2. 为什么需要依赖:应用程序需要 IoC 容器来提供对象需要的外部资源;
  3. 谁注入谁:很明显是 IoC 容器注入应用程序某个对象,应用程序依赖的对象;
  4. 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

IoC 和 DI 由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以 2004 年大师级人物 Martin Fowler 又给出了一个新的名字:“依赖注入”,相对 IoC 而言,“依赖注入”明确描述了“被注入对象依赖 IoC 容器配置依赖对象”。

总结

控制反转是一种面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见一种的方式叫做依赖注入控制反转不是一种技术,而是一种思想,其基本思想是:借助于第三方(IoC 容器)实现具有依赖关系的对象之间的解耦控制反转作为 Spring 的核心,让IoC 容器通过依赖注入的方式使得创建依赖对象的控制权由对象转移到IoC 容器

参考文献

IoC 之 2.1 IoC 基础 ——跟我学 Spring3