javascript
【Spring学习】IOC容器
1、IOC的理論背景
我們知道在面向對象設計的軟件系統中,它的底層都是由N個對象構成的,各個對象之間通過相互合作,最終實現系統地業務邏輯。
圖1 軟件系統中耦合的對象
如果我們打開機械式手表的后蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是這樣的一個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互嚙合在一起,協同工作,共同完成某項任務。我們可以看到,在這樣的齒輪組中,如果有一個齒輪出了問題,就可能會影響到整個齒輪組的正常運轉。
齒輪組中齒輪之間的嚙合關系,與軟件系統中對象之間的耦合關系非常相似。對象之間的耦合關系是無法避免的,也是必要的,這是協同工作的基礎。現在,伴隨著工業級應用的規模越來越龐大,對象之間的依賴關系也越來越復雜,經常會出現對象之間的多重依賴性關系,因此,架構師和設計師對于系統的分析和設計,將面臨更大的挑戰。對象之間耦合度過高的系統,必然會出現牽一發而動全身的情形。
圖2 對象之間的依賴關系
耦合關系不僅會出現在對象與對象之間,也會出現在軟件系統的各模塊之間,以及軟件系統和硬件系統之間。如何降低系統之間、模塊之間和對象之間的耦合度,是軟件工程永遠追求的目標之一。為了解決對象之間的耦合度過高的問題,軟件專家Michael Mattson 1996年提出了IOC理論,用來實現對象之間的“解耦”,目前這個理論已經被成功地應用到實踐當中。
2、什么是IOC
IOC是Inversion of Control的縮寫,多數書籍翻譯成“控制反轉”。
1996年,Michael Mattson在一篇有關探討面向對象框架的文章中,首先提出了IOC 這個概念。對于面向對象設計及編程的基本思想,前面我們已經講了很多了,不再贅述,簡單來說就是把復雜系統分解成相互合作的對象,這些對象類通過封裝以后,內部實現對外部是透明的,從而降低了解決問題的復雜度,而且可以靈活地被重用和擴展。
IOC理論提出的觀點大體是這樣的:借助于“第三方”實現具有依賴關系的對象之間的解耦。如下圖:
圖3 IOC解耦過程大家看到了吧,由于引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關系,齒輪之間的傳動全部依靠“第三方”了,全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“粘合劑”的作用,把系統中的所有對象粘合在一起發揮作用,如果沒有這個“粘合劑”,對象與對象之間會彼此失去聯系,這就是有人把IOC容器比喻成“粘合劑”的由來。
我們再來做個試驗:把上圖中間的IOC容器拿掉,然后再來看看這套系統:
我們現在看到的畫面,就是我們要實現整個系統所需要完成的全部內容。這時候,A、B、C、D這4個對象之間已經沒有了耦合關系,彼此毫無聯系,這樣的話,當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關系已經降低到了最低程度。所以,如果真能實現IOC容器,對于系統開發而言,這將是一件多么美好的事情,參與開發的每一成員只要實現自己的類就可以了,跟別人沒有任何關系!
我們再來看看,控制反轉(IOC)到底為什么要起這么個名字?我們來對比一下:
軟件系統在沒有引入IOC容器之前,如圖1所示,對象A依賴于對象B,那么對象A在初始化或者運行到某一點的時候,自己必須主動去創建對象B或者使用已經創建的對象B。無論是創建還是使用對象B,控制權都在自己手上。
軟件系統在引入IOC容器之后,這種情形就完全改變了,如圖3所示,由于IOC容器的加入,對象A與對象B之間失去了直接聯系,所以,當對象A運行到需要對象B的時候,IOC容器會主動創建一個對象B注入到對象A需要的地方。
通過前后的對比,我們不難看出來:對象A獲得依賴對象B的過程,由主動行為變為了被動行為,控制權顛倒過來了,這就是“控制反轉”這個名稱的由來。
3、IOC也叫依賴注入(DI)
2004年,Martin Fowler探討了同一個問題,既然IOC是控制反轉,那么到底是“哪些方面的控制被反轉了呢?”,經過詳細地分析和論證后,他得出了答案:“獲得依賴對象的過程被反轉了”。控制被反轉之后,獲得依賴對象的過程由自身管理變為了由IOC容器主動注入。于是,他給“控制反轉”取了一個更合適的名字叫做“依賴注入(Dependency Injection)”。他的這個答案,實際上給出了實現IOC的方法:注入。所謂依賴注入,就是由IOC容器在運行期間,動態地將某種依賴關系注入到對象之中。
所以,依賴注入(DI)和控制反轉(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關系注入的方式,實現對象之間的解耦。
學過IOC的人可能都看過Martin Fowler(老馬,2004年post)的這篇文章:Inversion of Control Containers and the Dependency Injection pattern。
4、IOC的優缺點
以我的經驗來看,IoC使用Spring容器帶來一下好處:
?靈活性
?使改變一個廣泛使用的接口的實現類是簡單的(如通過生產實例取代模擬web服務)
?改變檢索策略對于一個給定的類更簡單(例如移動一個服務從類路徑到JNDI樹)
?添加攔截器是容易的,并且可以只在一個單獨的地方做(如添加一個緩存攔截器到一個基于jdbc的DAO中)
?易讀性
?這個項目有一個統一和一致的組件模型而不是到處都是工廠 (e.g. DAO factories)
?代碼簡短,都有依賴查找代碼(例如,調用JNDI初始上下文)
?可測試性
?依賴關系很容易取代模擬當他們通過構造函數或setter暴露時
?容易測試導致更多測試
?更多測試會導致更好的代碼質量,和低耦合、高內聚
使用IOC框架產品能夠給我們的開發過程帶來很大的好處,但是也要充分認識引入IOC框架的缺點,做到心中有數,杜絕濫用框架。
第一、軟件系統中由于引入了第三方IOC容器,生成對象的步驟變得有些復雜,本來是兩者之間的事情,又憑空多出一道手續,所以,我們在剛開始使用IOC框架的時候,會感覺系統變得不太直觀。所以,引入了一個全新的框架,就會增加團隊成員學習和認識的培訓成本,并且在以后的運行維護中,還得讓新加入者具備同樣的知識體系。
第二、由于IOC容器生成對象是通過反射方式,在運行效率上有一定的損耗。如果你要追求運行效率的話,就必須對此進行權衡。
第三、具體到IOC框架產品(比如:Spring)來講,需要進行大量的配制工作,比較繁瑣,對于一些小的項目而言,客觀上也可能加大一些工作成本。
第四、IOC框架產品本身的成熟度需要進行評估,如果引入一個不成熟的IOC框架產品,那么會影響到整個項目,所以這也是一個隱性的風險。
我們大體可以得出這樣的結論:一些工作量不大的項目或者產品,不太適合使用IOC框架產品。另外,如果團隊成員的知識能力欠缺,對于IOC框架產品缺乏深入的理解,也不要貿然引入。最后,特別強調運行效率的項目或者產品,也不太適合引入IOC框架產品,像WEB2.0網站就是這種情況。
5、IOC容器的技術剖析
IOC中最基本的技術就是“反射(Reflection)”編程,目前.Net C#、Java和PHP5等語言均支持,其中PHP5的技術書籍中,有時候也被翻譯成“映射”。有關反射的概念和用法,大家應該都很清楚,通俗來講就是根據給出的類名(字符串方式)來動態地生成對象。這種編程方式可以讓對象在生成時才決定到底是哪一種對象。反射的應用是很廣泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做為最基本的技術手段。
6、IOC容器的一些產品
Sun ONE技術體系下的IOC容器有:輕量級的有Spring、Guice、Pico Container、Avalon、HiveMind;重量級的有EJB;不輕不重的有JBoss,Jdon等等。Spring框架作為Java開發中SSH(Struts、Spring、Hibernate)三劍客之一,大中小項目中都有使用,非常成熟,應用廣泛,EJB在關鍵性的工業級項目中也被使用,比如某些電信業務。
.Net技術體系下的IOC容器有:Spring.Net、Castle等等。Spring.Net是從Java的Spring移植過來的IOC容器,Castle的IOC容器就是Windsor部分。它們均是輕量級的框架,比較成熟,其中Spring.Net已經被廣泛應用于各種項目中。
總之就是很多很多,不甚枚舉…..
以上內容參考以下博文,感謝作者分享:
http://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html
總結
以上是生活随笔為你收集整理的【Spring学习】IOC容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Spring学习】Spring简介
- 下一篇: 【Spring学习】Spring的AOP