J2EE应用开发中,经常遇到的问题就是:如何将不同的组件组装成为一个内聚的应用程序?IoC模式可以解决这个问题,其目标是将组件的配置与使用分离开。
IoCInversion of Control,控制反转[1],其原理是基于OO设计原则的The Hollywood PrincipleDon't call us, we'll call you。也就是说,所有的组件[2]都是被动的(Passive),所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。
要说明IoC模式最好的方法是使用代码。下边是一段正常的代码。
class ClassA...
  public String aMethod(String arg){
    String result = instanceOfClassB.bMethod();
    do something;
    return result;
  }
在上边的代码里,我们要解决的问题是:ClassA如何获得ClassB的实例?一个最直接的方法是在aMethod里声明:
IClassB instanceOfClassB = new ClassB();
这里使用了一个接口IClassB
问题是,如果出现这样的情况:继续使用ClassA,但要求用IClassB的另一个实现ClassB2代替ClassB呢?更概括一点说:ClassA怎样才能找到IClassB的具体实现?很明显,上述代码增加ClassAClassB的耦合度,以致于无法在不修改ClassA的情况下变更IClassB的具体实现。
IoC模式就是用于解决这样的问题。当然,还有其他的方法,比如Service Locator模式,但现在我们只关注IoC。如前所述,IoC容器负责初始化组件(如IClassB),并将实例交给使用者。使用代码或配置文件以声明的方式将接口与实例关联起来,IoC容器负责进行实际的调用处理。对于调用者,只需要关注接口就行了。
根据实例传入方式的不同,IoC分为type 1 IoC(接口注入[3])、type 2 IoC(设值方法注入)和type 3 IoC(构造子注入)。分别用代码说明如下:
type 1 IoC(接口注入)
public interface GetClassB {
  void getClassB(IClassB instanceOfClassB);
}
 
class ClassA implements GetClassB…
  IClassB instanceOfClassB;
  void getClassB(IClassB instanceOfClassB) {
this.instanceOfClassB = instanceOfClassB;
  }
type 2 IoC(设值方法注入)
class ClassA...
  IClassB instanceOfClassB;
  public void setFinder(IClassB instanceOfClassB) {
    this.instanceOfClassB = instanceOfClassB;
  }
type 3 IoC(构造子注入)
class ClassA…
ClassB instanceOfClassB;
  public classA(IClassB instanceOfClassB) {
    this. instanceOfClassB = instanceOfClassB;
  }
  Spring使用的是type 2 IoC