一. Ioc 的含义
Ioc英文为 Inversion of Control,即反转控制 , 新的Ioc模式 Dependency Injection模式是依赖注射的意思,也就是将依赖
先剥离,然后在适当时候再注射进入。
二. Ioc的三种模式
第一种类型 | 从JNDI或ServiceManager等获得被调用者,这里类似ServiceLocator模式。 | 1. EJB/J2EE 2. Avalon(Apache的一个复杂使用不多的项目) |
第二种类型 | 使用JavaBeans的setter方法 | 1. Spring Framework, 2. WebWork/XWork |
第三种类型 | 在构造方法中实现依赖 | 1. PicoContainer, 2. HiveMind |
三. 工厂模式和Ioc
主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实
还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。
使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。
所以,Ioc并没有消除B和C之间这样的联系,只是转移了这种联系。
这种联系转移实际也是一种分离关注,它的影响巨大,它提供了AOP实现的可能。
Ioc和AOP
AOP我们已经知道是一种面向切面的编程方式,由于Ioc解放自由了B类,而且可以向B类实现注射C类具体实现,
如果把B类想像成运行时的横向动作,无疑注入C类子类就是AOP中的一种Advice,如下图:
四. Ioc 的几种实现类型
(1)接口注入
通常做法是利用接口将调用者与实现者分离。
public class Sport {
private InterfaceBall ball; //InterfaceBall是定义的接口
public void init() {
//Basketball实现了InterfaceBall接口
ball = (InterfaceBall) Class.forName("Basketball").newInstance();
}
}
Sport类在编译期依赖于InterfaceBall的实现,为了将调用者与实现者分离,我们动态生成Basketball类并通了强制类型转换为InterfaceBall。Apache Avalon是一个典型的Type1型IoC容器。
(2)setter方法注入
在类中暴露setter方法来实现依赖关系。
public class Sport {
private InterfaceBall ball;
public void setBall(InterfaceBall arg) {
ball = arg;
}
}
这种方式对已经习惯了JavaBean的程序员而言,更显直观。Spring就是实现了该类型的轻量级容器。
(3)构造子注入
即通过构造方法完成依赖关系。
public class Sport {
private InterfaceBall ball;
public Sport(InterfaceBall arg) {
ball = arg;
}
}
可以看到,通过类的构造方法建立依赖关系。由于Type3在构造期就形成了对象的依赖关系,即存对象的重用变的困难。有些框架需要组件提供一个默认的构造方法,此时就体现了Type3的局限性。通常所有的参数都是通过构造方法注入的,当对象间的依赖关系较多时,构造方法就显的比较复杂,不利于单元测试。PicoContainer就是实现了Type3依赖注入模式的轻量级容器。