Spring 的核心概念是 IoC,IoC 的抽象概念是「依赖关系的转移」,像是「高层模块不应该依赖低层模块,而是模块都必须依赖于抽象」是
  IoC 的一种表现,「实现必须依赖抽象,而不是抽象依赖实现」也是 IoC 的一种表现,「应用程序不应依赖于容器,而是容器服务于应用程序」也是
  IoC 的一种表现。 
  
  IoC 全名 Inversion of Control,如果中文硬要翻译过来的话,就是「控制反转」。初看 IoC,从字面上不容易了解其意义,我觉得要了解 IoC,要先从 Dependency Inversion 开始了解,也就是依赖关系的反转。 
  
  Dependency Inversion The Dependency Inversion Principle 有清楚的解释。
  
  简单的说,在模块设计时,高层的抽象模块通常是与业务相关的模块,它应该具有重用性,而不依赖于低层的实作模块,例如如果低层模块原先是软盘存取模式,而高层模块是个存盘备份的需求,如果高层模块直接叫用低层模块的函式,则就对低层模块产生了依赖关系。 
  
  举个例子,例如下面这个程序: 
#include.... void save() { .... saveToFloppy() } } 
  由于save()程序依赖于依赖于saveToFloppy(),如果今天要更换低层的存储模块为Usb碟,则这个程序没有办法重用,必须加以修改才行,
  低层模块的更动造成了高层模块也必须跟着更动,这不是一个好的设计方式,在设计上希望模块都依赖于模块的抽象,这样才可以重用高层的业务设计。 
  
  如果以对象导向的方式来设计,依赖反转(Dependency Inversion)的解释变为程序不应依赖实作,而是依赖于抽象,实作必须依赖于抽象。来看看下面这个 Java 程序: 
public class BusinessObject {
	private FloppyWriter writer = new FloppyWriter();
	....
	public void save() {
		...
		writer.saveToFloppy();
	}
}
在这个程序中,BusinessObject 的存盘依赖于实际的 FloppyWriter,如果今天想要将存盘改为存至 Usb 碟,则必须修改或继承 BusinessObject 进行扩展,而无法直接使用BusinessObject。 
  
如果透过接口的宣告,可以改进此一情况,例如: 
public interface IDeviceWriter {
	public void saveToDevice();
}
public class BusinessObject {
	private IDeviceWriter writer;
	public void setDeviceWriter(IDeviceWriter writer) {
		this.writer = writer;
	}
	public void save() {
		....
		writer.saveToDevice();
	}
}
这样一来,BusinessObject 就是可重用的,如果今天有存储至 Floppy 或 Usb 碟的需求,只要实作 IDeviceWriter 即可,而不用修改 BusinessObject:
public class FloppyWriter implement IDeviceWriter {
	public void saveToDevice() {
		....
		// 实际储存至Floppy的程序代码
	}
}
public class UsbDiskWriter implement IDeviceWriter {
	public void saveToDevice() {
		....
		// 实际储存至UsbDisk的程序代码
	}
}
  从这个角度来看,Dependency Inversion 的意思即是程序不依赖于实作,而是程序与实作都要依赖于抽象。 
  
  IoC 的 Control
  是控制的意思,其实其背后的意义也是一种依赖关系的转移,如果A依赖于B,其意义即是B拥有控制权,您想要转移这种关系,所以依赖关系的反转即是控制关系
  的反转,藉由控制关系的转移,可以获得组件的可重用性,在上面的 Java 程序中,整个控制权从实际的 FloppyWriter 转移至抽象的
  IDeviceWriter 接口上,使得BusinessObject、FloppyWriter、UsbDiskWriter
  这几个实现依赖于抽象的 IDeviceWriter 接口。 
  
  程序的业务逻辑部份应是可以重用的,不应受到所使用框架或容器的影响,因为可能转移整个业务逻辑至其它的框架或容器,如果业务逻辑过于依赖容器,则转移至其它的框架或容器时,就会发生困难。 
  
  IoC 在容器的角度,可以用这么一句好莱坞名言来代表:"Don't call me, I'll call you." 以程序的术语来说的话,就是「不要向容器要求您所需要的(对象)资源,容器会自动将这些对象给您!」。IoC
  要求的是容器不侵入应用程序本身,应用程序本身提供好接口,容器可以透过这些接口将所需的资源注至至程序中,应用程序不向容器主动要求资源,故而不会依赖
  于容器的组件,应用程序本身不会意识到正被容器使用,可以随时从容器中脱离转移而不用作任何的修改,而这个特性正是一些业务逻辑中间件最需要的。