隨筆 - 81  文章 - 1033  trackbacks - 0
          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          在浮躁的年代里,我們進取心太切,患得患失;虛榮心太強,戰戰兢兢。一心爭強好勝,惟恐榜上無名。
          I think I can fly , and flying like a bird !
          程序員一名,已售出,缺貨中!

          我的郵件聯系方式

          用且僅用于MSN

          博客點擊率
          free web counter
          free web counter

          常用鏈接

          留言簿(36)

          隨筆檔案

          搜索

          •  

          積分與排名

          • 積分 - 187057
          • 排名 - 309

          最新評論

          閱讀排行榜

          評論排行榜

          摘自: http://news.csdn.net/n/20061228/100086.html

          這篇文章寫的很有意思,把晦澀難懂的術語用拍電影來表達,效果很不錯,特此轉載。

          概述

          ??? IoC(反向控制:Inverse of Control)是Spring容器的底層核心功能,AOP功能、聲明事務等功能在此基礎上生根開花。但是IoC這個重要的概念卻比較晦澀隱諱,拐彎抹角,不容易讓人望文生義,不能不說是一大遺憾。不過IoC確實包括很多內涵,它涉及到代碼解耦,設計模式優化等問題的考量。
          2006年多部賀歲大片以讓人應接不暇的頻率紛至沓來,其中張之亮的《墨攻》算是比較出彩的一部,講述了戰國時期墨家人革離幫助梁國反抗趙國侵略的個人英雄主義故事,恢宏壯闊,渾雄凝重的歷史場面相當震撼。其中有一個場景:當劉德華所飾的墨者革離到達梁國都城下,城上梁國守軍問:“來者何人?”,劉德華回答:“墨者革離!”,我們不妨用Java對這段“城門問對”的場景進行編劇并借由這個例子來理解IoC的內涵。

          劇本和飾演者耦合
          ?
          MoAttack代表《墨攻》的劇本,cityGetAsk()代表“城門問對”這段劇情,LiuDeHua是具體飾演者劉天王:
          ??????????????????????????????? 代碼清單 1? MoAttack:通過演員安排劇本

          public class MoAttack { public void cityGateAsk(){ LiuDeHua ldh =new LiuDeHua(); ① 演員直接侵入劇本 ldh.responseAsk("墨者革離!"); } }
          ? 我們會發現以上劇本在①處,作為具體飾演者的劉德華直接侵入到劇本中,使劇本和演員直接耦合在一起:
          ???????????????????????

          ?????????????????????????????????????????????????? ??????? 圖 1 劇本和演員直接耦合
          ? 一個明智的編劇在劇情創作時應圍繞故事的角色進行,而不應考慮角色的具體飾演者,這樣才可能在劇本投拍時自由地遴選任何適合的演員,而非綁定在劉德華一人身上。通過以上的分析,我們知道需要為該劇本主人公革離定義一個接口,以角色進行劇情安排,飾演者實現角色的接口:
          ??????????????? 代碼清單 2 MoAttack:引入劇本角色

          publicclass MoAttack...{ publicvoid cityGateAsk() ...{ GeLi geli =new LiuDeHua(); ① 引入革離角色接口 geli.responseAsk("墨者革離!"); ② 通過接口開展劇情 } }


          ??? 在①處引入了劇本的角色——革離,劇本的情節通過角色展開,在拍攝時角色的事跡由演員表現,如②處所示。因此墨攻、革離、劉德華三者的類圖關系如圖 2所示:
          ??


          ??? 我們希望劇本和演員無關,可是,在圖2中,我們看到MoAttack同時依賴于GeLi接口和LiuDeHua類,并沒有達到我們所期望的劇本僅依賴于角色的目的??墒墙巧罱K又必須通過具體的演員才能完成拍攝,如何將讓LiuDeHua和劇本無關而又能完成GeLi的具體動作呢?當然是在影片投拍時,導演將LiuDeHua安排在GeLi的角色上,通過導演之手將劇本、角色、飾演者裝配起來。


          ??????????????????????????????????????? 圖 3 劇本和飾演者解耦了
          ??? 通過引入導演,劇本和具體的飾演者解耦了,對應到軟件中,導演象是一個裝配器,將具體的飾演者賦給了劇本的角色。
          現在我們可以反過來講解IoC的概念了。IoC(Inverse of Control)的字面意思是控制反轉,它包括兩個層面的內容:其一是“控制”,其二是“反轉”,到底是什么東西的控制被反轉了呢?對應到前面的例子,“控制”是指GeLi角色扮演者的選擇控制權,“反轉”是指這種選擇控制權從《墨攻》劇本中移除,轉交到導演的手中。對于程序來說,即是某一接口具體實現類的選擇控制權從客戶類中移除,轉交給第三方來確定,客戶類不知道是哪個具體的實現類,它通過接口方法對實現類進行調用。

          ??? 因為IoC確實不夠開門見山,因此業界曾進行了廣泛的討論,最終軟件界的泰斗級人物Martin Fowler提出了DI(依賴注入:Dependency Injection)的概念,即將客戶類對接口實現類的依賴關系由第三方(容器或協作類)注入,以移除客戶類對具體接口實現類的依賴?!耙蕾囎⑷搿钡母拍铒@然比“控制反轉”直接達意,易于理解。

          IoC的三種類型

          ? 從注入方法上看,主要可以劃分為三種的注入類型,分別是構造函數注入、屬性注入和接口注入,Spring支持構造函數注入和屬性注入。下面我們繼續使用以上的例子說明這三種注入方法的區別。

          ■ 構造函數注入
          ??? 我們通過客戶類的構造函數,將接口實現類通過接口變量傳入,如代碼清單 3 3所示:
          ???????????????????? 代碼清單 3 MoAttack:通過構造函數注入革離扮演者

          ?

          publicclass MoAttack { private GeLi geli; public MoAttack(GeLi geli){ ① 注入革離的具體扮演者 this.geli = geli; }publicvoid cityGateAsk() { geli.responseAsk(“墨者革離!”); } }

          ???? MoAttack的構造函數不關心具體是誰扮演革離這個角色,只要在①處傳入的扮演者按劇本要求完成角色功能即可。
          角色的具體扮演者由導演來安排,如代碼清單 3 4所示:
          ??????????????????????????????????????????? 代碼清單 4 Director:通過構造函數注入革離扮演者

          publicclass Director { publicvoid direct(){ GeLi geli =new LiuDeHua(); ① 指定角色的扮演者 MoAttack moAttack =new MoAttack(geli); ② 注入具體扮演者到劇本中 moAttack.cityGateAsk(); } }

          ??? 在①處,導演安排劉德華飾演革離的角色,并在②處,將劉德華“注入”到墨攻的劇本中,然后開始“城門問答”劇段的演出工作。
          ??
          ■ 屬性注入
          ???? 有時,導演會發現,雖然革離是影片《墨攻》的第一主人公,但并非每場戲都需要革離的出現,通過構造函數方式注入顯得很不妥當,在這種情況下,可以使用屬性注入進行改造。屬性注入通過setter方法完成客戶類所需依賴的注入,更靈活,更方便。
          ??????????????????? 代碼清單 5 MoAttack:通過setter方法注入革離扮演者

          publicclass MoAttack { private GeLi geli; publicvoid setGeli(GeLi geli) { ① 屬性注入方法 this.geli = geli; }publicvoid cityGateAsk() { geli.responseAsk("墨者革離"); } }

          ?? MoAttack在①處為geli屬性提供一個setter方法,以便讓導演在拍需要革離的戲時才將注入geli的具體扮演者,而不需要劉德華從頭到尾跟著墨攻劇組跑。
          ????? 代碼清單 6 Director:通過setter方法注入革離扮演者

          publicclass Director { publicvoid direct(){ GeLi geli =new LiuDeHua(); MoAttack moAttack =new MoAttack(); moAttack.setGeli(geli); ① 調用屬性setter方法注入 moAttack.cityGateAsk(); } }

          ??? 和通過構造函數注入革離扮演者不同,在實例化MoAttack時,并未指定任何扮演者,而是在實例化MoAttack后,調用其setGeli()方法注入扮演者。按照類似的方式,我們還可以為劇本中其他如巷淹中,梁王等角色分別提供注入的setter方法,導演即可以根據所拍劇段的不同,注入所需要的角色了。

          ■ 接口注入
          ???? 將客戶類所有注入的方法抽取到一個接口中,客戶類通過實現這一接口提供注入的方法。為了采取接口注入的方式,需要聲明一個額外的接口:

          publicinterface ActorArrangable { void injectGeli(GeLi geli); }

          ??? 然后,MoAttack實現這個接口并實現接口中的方法:
          ???????????? 代碼清單 7 MoAttack:通過接口方法注入革離扮演者

          publicclass MoAttack implements ActorArrangable { private GeLi geli; publicvoid injectGeli (GeLi geli) { ① 實現接口方法 this.geli = geli; }publicvoid cityGateAsk() { geli.responseAsk("墨者革離"); } }

          Director通過ActorArrangable的injectGeli()方法完成扮演者的注入工作。
          ?? 代碼清單 8 Director:通過接口方法注入革離扮演者

          publicclass Director { publicvoid direct(){ GeLi geli =new LiuDeHua(); MoAttack moAttack =new MoAttack(); moAttack. injectGeli (geli); moAttack.cityGateAsk(); } }

          ?? 由于通過接口注入需要額外聲明一個接口,增加了類的數目,而且它的效果和屬性注入并無本質區別,因此我們不提倡這種方式。

          通過容器完成依賴關系的建立

          ??? 雖然MoAttack和LiuDeHua實現了解耦,無需關注實現類的實例化工作,但這些工作在代碼中依然存在,只是轉移到Director中而已,導致導演的權力非常大,潛規則不斷滋生。假設某一制片人想改變這一局面,在相中某個劇本后,通過一個“海選”或者第三公正中介來選擇導演、演員,讓他們各司其職,那劇本、導演、演員就都實現解耦了。
          所謂媒體“海選”和中介機構在程序領域即是一個第三方容器,它幫助我們完成類的初始化和裝配工作,讓我們從這些底層的實現類實例化,依賴關系的裝配中脫離出來,專注于更有意思的業務代碼的編寫工作,那確實是挺愜意的事情。Spring就是這樣一個容器,它通過配置文件描述類之間的依賴關系,下面是Spring配置文件的對以上實例進行配置的樣式代碼:

          <beans><bean id="geli"class="com.baobaotao.LiuDeHua"></bean><bean id="moAttack"class=" com.baobaotao.MoAttack"><property name="geli"><ref bean="geli"/></property></bean></beans>

          ???? 通過new XmlBeanFactory(“beans.xml”)等方式即可啟動容器,在容器啟動時,Spring根據配置文件的描述信息,通過Java的反射機制自動實例化Bean并完成依賴關系的建立,從容器中即可返回準備就緒的Bean實例,以待后續的使用。

          小結

          ??? 隨著Spring的廣泛應用,IoC的概念被越來越多的提及,可是很多說者因為IoC本身的晦澀往往并不清楚其中的意義,我們通過時下叫座的賀歲大片《墨攻》來解釋IoC的概念,相信對加深IoC概念的理解有所補益。

          posted on 2007-01-11 23:08 cresposhi 閱讀(1066) 評論(19)  編輯  收藏

          FeedBack:
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-17 15:36 梅穎
          看不懂,幸虧我冒搞這個,好累人啊看的我  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 11:42 kirari_wxy
          施偉是不是武漢人?怎么你老婆的留言都是武漢話?呵呵 看著親切。  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 11:51 梅穎
          是啊是啊,我是正宗的武漢人,他才不是列,他是武漢的女婿,呵呵,你是武漢的么?你好你好,不在武漢呀?  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 12:10 kirari_wxy
          我是標準的武漢人哦,呵呵,不過來上海2年多了。  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 13:53 梅穎
          那上海好不好列?  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:00 kirari_wxy
          當然好,不過吃的東西不行,冇得一個東西好吃,這是所有外地人的痛苦。  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:03 梅穎
          自己做飯啊,我在深圳就是自己做飯吃列,到外面吃的少  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:13 kirari_wxy
          不會咧,我從來冇進過廚房,以前都是在外面吃,現在合租以后有同事做飯。  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:19 梅穎
          你還一點個學習的精神都冒的列,果然是武漢的兒子牙啊  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:27 kirari_wxy
          一個人住做飯也太麻煩了撒  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:44 梅穎
          那你先說說我們要準備什么,過去之前,呵呵,都老人了,快點建議一哈,還老鄉列,要不過去給你代點熱干面,呵呵  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 14:57 kirari_wxy
          沒什么,多帶點錢就可以了,剛來的話用錢的地方比較多,特別是租房。各種證件帶齊,戶口之類不能帶的至少要帶上復印件,如果進比較大的公司,要出國出差的話,提前辦個護照也行,來了再回去辦就麻煩了。  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 15:02 梅穎
          這么麻煩啊,天哪,那我先去辦一個,哈哈  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-01-31 21:07 施偉
          真是老鄉見老鄉兩眼淚汪汪啊 你們。。。 呵呵
          繼續繼續 我隱身先   回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-02-01 12:45 梅穎
          呵呵,我覺得墨攻還可以(換話題)!  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-02-02 12:32 小祝
          ...什么呀,成聊天室了.哈哈,技術問題要嚴肅.寫的不錯,可惜我看不懂...  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-02-02 15:13 梅穎
          那你怎么知道寫的可以,切,你才是侮辱技術問題列,呵呵,還說我們  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-02-02 20:44 施偉
          真是口無遮攔的老婆,哎。。。
          我的朋友都逃不過她的魔掌。。。呵呵  回復  更多評論
            
          # re: 看《墨攻》理解IoC—Spring底層核心 (寫的很有意思)【 轉載】 2007-02-02 22:56 梅穎
          呵呵我成東方不敗了,人妖?
            回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 崇文区| 宁蒗| 新乡市| 综艺| 金阳县| 海宁市| 盘山县| 合江县| 鸡东县| 彭山县| 河津市| 忻城县| 西安市| 康平县| 武宁县| 合阳县| 特克斯县| 山阴县| 高阳县| 阳城县| 阿图什市| 永清县| 谢通门县| 永德县| 临澧县| 延寿县| 铜陵市| 祁连县| 泗水县| 建昌县| 仪陇县| 大丰市| 承德市| 稻城县| 盖州市| 绍兴县| 洛扎县| 文成县| 镇江市| 曲阜市| 彭水|