通常在框架中,控制反转是—个非常重要的概念,它最著名的形式就是所谓好莱坞原则∶”不要打电话过来,我们会打给你。“在本书的剩下部分,我们将用通用的缩写形式 IoC来称呼它。


IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

依赖注入(Dependency Injection)是时下最流行的 IoC类型,它利用 IoC 去消除所有的查找(lookup)代码,让容器自动决定对象间的依赖关系。
image.png

IOC实现策略

分为依赖查找和依赖注入两种

依赖查找

不好用

依赖注入(DI)

组件不做定位查询,只提供普通的 Java方法让容器去决定依赖关系。容器全
权负责组件的装配,它会把符合依赖关系的对象通过 JavaBean 属性或者构造子传递给需要的对象。通过 JavaBean 属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造子参数传入的做法称为构造子注入(Constructor Injection)。

依赖注入——是一种更可取的方式∶ 让容器去全权负责依赖查询,受管对象只需暴露 JavaBean 的 setter 方法或者带参数的构造子,使容器可以在初始化时组装对象的依赖关系。由于这种方式不依赖于特定的容器 API 或接口,我称之为”基于语言的 IoC(language-based IoC)”。

设值方式注入

使用设值方法注入(Setter Injection)时,组件通过 JavaBean 属性来表达自已需要配置的值和依赖的对象,因此这种注入方式是建立在 JavaBean 规范之上的。和依赖注入一样,这个概念也不是 Java特有的。其他很多语言也支持类似JavaBean 的规范,譬如C#也有”属性”(property)的概念。

  1. private MyCollaborator myCollaborator;
  2. public void setMyCollaborator(MyCollaborator myCollaborator){
  3. this.myCollaborator = myCollaborator;
  4. }

当容器实例化应用对象之后,就会立即调用后者的设值方法,传入合适的参数。因此,这里不会涉及线程问题。


这里是在 JavaBean 的属性里声明对象之间的依赖关系。对于基本类型(例如 int 型)的属性值,同样可以用 JavaBean 属性的形式将其抽取到配置文件中。这种做法简化了代码,使其可以在不同环境下运行,而且应用对象仅仅依赖那些确实需要在业务逻辑中用到的资源和对象,而不必依赖容器。同时,繁琐的异常操作也不再必要,因为容器可以在构造的时候检查出配置(依赖关系)的错误,而不是在运行时才作检查。简而言之, 先前所说到的问题都得到了解决。


可以看出,这是一个普通的 Java 类,没有依赖 IoC 容器。所以,它可以在任何环境下运行,就算没有容器也是一样。


构造子注入

使用构造子注入(Constructor Injection)时,组件以构造子参数的形式描述自己需要的依赖关系。

  1. public MyBusinessObject (DataSource ds,MyCollaborator myCollaborator int myTntValue){
  2. this.ds - ds;
  3. this.myCollaborator = myCollaborator;
  4. this.my IntValue = myIntValue;
  5. }

IOC容器

这里主要说spring

Sping框架

Spring 框架对设值方法依赖注入和构造子依赖注入都提供了完善的支持。

几乎所有的 Java 对象可以在 Spring 容器中使用。不过,如果想获得IoC 的全部好处, Java 类就必须通过 JavaBean 属性或者构造子参数来进行配置。

一个好的 IoC 组件根本不需要自己动手查找资源和依赖对象——尽管 IoC 容器环境中也会提供这样的查找能力。某些遗留类也许会通过别的途径读取它们自己的配置信息,这也会损害 IoC 容器希望提供的概念一致性。

一般情况下,Spring 的 IoC 是通过元数据进行配置的,不过它并不强求任何特定的元数据表现形式。你可以实现 Spring 的 BeanDefinitionReader 接口,使其能够理解你自定义的元数据表现形式,并用它来配置 Spring 的 IoC容器。不过,大多数时候,我们还是用 XML的形式来表现元数据,此时一个实现了MyBusinessObject 接口的 JavaBean 的配置大致如下∶
image.png
这个例子无法体现XML表示法的其他好处,比如依赖检查,自动装配,支持集合,指定初始化方法和销毁方法等。

其他具体关于Spring的内容之后具体再说。