IoChtml
IoC
:
Inversion of Control
,控制反轉,
控制權從應用程序轉移到框架(如
IoC
容器),是框架共有特性
一、爲何須要IoC容器
1.一、應用程序主動控制對象的實例化及依賴裝配
- A a = new AImpl();
- B b = new BImpl();
- a.setB(b);
本質:建立對象,主動實例化,直接獲取依賴,主動裝配
缺點:更換實現須要從新編譯源代碼
很難更換實現、難於測試
耦合實例生產者和實例消費者
- A a = AFactory.createA();
- B b = BFactory.createB();
- a.setB(b);
本質:建立對象,被動實例化,間接獲取依賴,主動裝配 (簡單工廠)
缺點:更換實現須要從新編譯源代碼
很難更換實現、難於測試
- A a = Factory.create(「a」);
- B b = Factory.create(「b」);
- a.setB(b);
<!—配置.properties-->
本質:建立對象,被動實例化,間接獲取依賴, 主動裝配
(工廠+反射+properties配置文件、
Service Locator、註冊表)
缺點:冗餘的依賴裝配邏輯
我想直接:
//返回裝配好的a
- A a = Factory.create(「a」);
1.二、可配置通用工廠:
工廠主動控制,應用程序被動接受,控制權從應用程序轉移到工廠
- A a = Factory.create(「a」);
<!—配置文件-->
- <bean id=「a」 class=「AImpl」>
- <property name=「b」 ref=「b」/>
- </bean>
- <bean id=「b」 class=「BImpl」/>
本質:建立對象和裝配對象,
被動實例化,被動接受依賴,被動裝配
(工廠+反射+xml配置文件)
缺點:不通用
步驟:
一、讀取配置文件根據配置文件經過反射
建立AImpl
二、發現A須要一個類型爲B的屬性b
三、到工廠中找名爲b的對象,發現沒有,讀取
配置文件經過反射建立BImpl
四、將b對象裝配到a對象的b屬性上
【組件的配置與使用分離開(解耦、更改實現無需修改源代碼、易於更好實現) 】
- A a = ApplicationContext.getBean(「a」);
<!—配置文件-->
- <bean id=「a」 class=「AImpl」>
- <property name=「b」 ref=「b」/>
- </bean>
- <bean id=「b」 class=「BImpl」/>
本質:建立對象和裝配對象、管理對象生命週期
被動實例化,被動接受依賴,被動裝配
(工廠+反射+xml配置文件)
通用
IoC
容器:實現了
IoC
思想的容器就是
IoC
容器
二、IoC
容器特色
【
1
】無需主動new對象;而是描述對象應該如何被建立便可
IoC
容器幫你建立,即被動實例化;
【2】不須要主動裝配對象之間的依賴關係,而是描述須要哪一個服務(組件),
IoC
容器會幫你裝配(即負責將它們關聯在一塊兒),被動接受裝配;
【3】主動變被動,好萊塢法則:別打電話給咱們,咱們會打給你;
【4】迪米特法則(最少知識原則):不知道依賴的具體實現,只知道須要提供某類服務的對象(面向抽象編程),鬆散耦合,一個對象應當對其餘對象有儘量少的瞭解,不和陌生人(實現)說話
【5】IoC是一種讓服務消費者不直接依賴於服務提供者的組件設計方式,是一種減小類與類之間依賴的設計原則。
三、理解
IoC
容器問題關鍵:控制的哪些方面被反轉了?
一、誰控制誰?爲何叫反轉? ------
IoC
容器控制,而之前是應用程序控制,因此叫反轉
二、控制什麼? ------
控制應用程序所須要的資源(對象、文件
……
)
三、爲何控制? ------
解耦組件之間的關係
四、控制的哪些方面被反轉了? ------
程序的控制權發生了反轉:從應用程序轉移到了
IoC
容器。
思考:
1: IoC/DI等同於工廠嗎?
2: IoC/DI跟之前的方式有什麼不同?
領會:
主從換位的思想
四、實現了
IoC
思想的
容器
就是輕量級容器嗎
?
若是僅僅由於使用了控制反轉就認爲這些輕量級容器不同凡響,就好象在說個人轎車不同凡響由於它有四個輪子?
容器:提供組件運行環境,管理組件聲明週期(無論組件如何建立的以及組件之間關係如何裝配的);
IoC容器不只僅具備容器的功能,並且還具備一些其餘特性---如依賴裝配
控制反轉概念太普遍,讓人迷惑,後來
Martin
Fowler 提出依賴注入概念
Martin
Fowler Inversion of Control Containers and the Dependency Injection pattern
http://martinfowler.com/articles/injection.html
DI
二、什麼是DI
DI
:依賴注入(
Dependency Injection
)
:用一個單獨的對象(裝配器)來
裝配對象之間的依賴關係
。
二、理解
DI
問題關鍵
誰依賴於誰? -------
應用程序依賴於
IoC
容器
爲何須要依賴? -------
應用程序依賴於
IoC
容器裝配類之間的關係
依賴什麼東西? -------
依賴了
IoC
容器的裝配功能
誰注入於誰? -------
IoC
容器注入應用程序
注入什麼東西? -------
注入應用程序須要的資源(類之間的關係)
更能描述容器其特色的名字——「依賴注入」(Dependency Injection)
IoC容器應該具備依賴注入功能,所以也能夠叫DI容器
三、DI
優勢
【1】幫你看清組件之間的依賴關係,只須要觀察依賴注入的機制(setter/構造器),就能夠掌握整個依賴(類與類之間的關係)。
【2】組件之間的依賴關係由容器在運行期決定,形象的來講,即由容器動態的將某種依賴關係注入到組件之中。
【3】依賴注入的目標並不是爲軟件系統帶來更多的功能,而是爲了提高組件重用的機率,併爲系統搭建一個靈活、可擴展的平臺。經過依賴注入機制,咱們只須要經過簡單的配置,而無需任何代碼就可指定目標須要的資源,完成自身的業務邏輯,而不用關心具體的資源來自何處、由誰實現。
使用
DI
限制:組件和裝配器(IoC容器)之間不會有依賴關係,所以組件沒法從裝配器那裏得到更多服務,只能得到配置信息中所提供的那些。
四、
實現方式
一、構造器注入
二、setter注入
三、接口注入:在接口中定義須要注入的信息,並經過接口完成注入
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
使用
IoC/DI
容器開發須要改變的思路
一、應用程序不主動建立對象,但要描述建立它們的方式。
二、在應用程序代碼中不直接進行服務的裝配,但要配置文件中描述哪個組件須要哪一項服務。容器負責將這些裝配在一塊兒。
其原理是基於OO設計原則的The Hollywood Principle:Don‘t call us, we’ll call you(別找我,我會來找你的)。也就是說,全部的組件都是被動的(Passive),全部的組件初始化和裝配都由容器負責。組件處在一個容器當中,由容器負責管理。
IoC
容器功能:實例化、初始化組件、裝配組件依賴關係、負責組件生命週期管理。
本質:
IoC:控制權的轉移,由應用程序轉移到框架;
IoC/DI容器:
由應用程序主動實例化對象
變被動等待對象(被動實例化);
DI: 由專門的裝配器裝配組件之間的關係;
IoC/DI容器:
由應用程序主動裝配對象的依賴
變應用程序被動接受依賴
關於IoC/DI與DIP之間的關係 詳見 http://www.iteye.com/topic/1122310?page=5#2335746spring
IoC/DI與迪米特法則 詳見http://www.iteye.com/topic/1122310?page=5#2335748編程