這篇短文基本上是改編自Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern,目的呢,是讓讀者能夠在最短時間內了解IoC的概念。這也是我一貫的“風格”:最短的文字、最精要的內容、最清晰的說明。希望我能做到,自勉^_^
在J2EE應用開發中,經常遇到的問題就是:如何將不同的組件組裝成為一個內聚的應用程序?IoC模式可以解決這個問題,其目標是將組件的配置與使用分離開。
IoC,Inversion of Control,控制反轉,其原理是基于OO設計原則的The Hollywood Principle:Don't call us, we'll call you。也就是說,所有的組件都是被動的(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的具體實現?很明顯,上述代碼增加ClassA和ClassB的耦合度,以致于無法在不修改ClassA的情況下變更IClassB的具體實現。
IoC模式就是用于解決這樣的問題。當然,還有其他的方法,比如Service Locator模式,但現在我們只關注IoC。如前所述,IoC容器負責初始化組件(如IClassB),并將實例交給使用者。使用代碼或配置文件以聲明的方式將接口與實例關聯起來,IoC容器負責進行實際的調用處理。對于調用者,只需要關注接口就行了。
根據實例傳入方式的不同,IoC分為type 1 IoC(接口注入)、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。