posts - 56, comments - 77, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          IoC 問(wèn)題域

          Posted on 2010-07-11 22:18 切爾斯基 閱讀(2325) 評(píng)論(3)  編輯  收藏

          IoC避不開(kāi)的一個(gè)問(wèn)題是如何處理應(yīng)用程序的模塊化, 因?yàn)镮oC通常針對(duì)單個(gè)對(duì)象提供了良好的支持, 比如依賴管理,生命周期管理,部署時(shí)配置甚至運(yùn)行時(shí)配置, 但往往一組內(nèi)聚的互相協(xié)作的對(duì)象才構(gòu)成應(yīng)用程序基本的構(gòu)建塊. 這組內(nèi)聚對(duì)象間的協(xié)作關(guān)系是實(shí)現(xiàn)細(xì)節(jié), 包括單個(gè)對(duì)象的構(gòu)造函數(shù)和屬性也是, 如果把這些暴露出來(lái), 固然可以提高靈活性, 但是以最后的部署階段的復(fù)雜性以及難以維護(hù)性為代價(jià)的. 以配置文件為例, 可能需要在包含了幾百個(gè)對(duì)象定義的配置文件中, 去改動(dòng)七八個(gè)屬性, 變換五六個(gè)實(shí)現(xiàn), 來(lái)適應(yīng)不同的運(yùn)行環(huán)境

          兩個(gè)解決這個(gè)問(wèn)題的方向, 一個(gè)是IoC框架提供模塊化支持, 以及部署時(shí)支持, 一種是IoC框架應(yīng)該避開(kāi)這個(gè)問(wèn)題, 這本不屬于IoC的范圍, 應(yīng)該交由專門的模塊化框架如OSGi去解決

          在我相對(duì)熟悉的IoC框架中, Autofac試圖提供"Module"這個(gè)概念來(lái)解決一部分問(wèn)題. 對(duì)象間的協(xié)作可以隱藏在Module對(duì)象中, 一些必要的參數(shù)可以通過(guò)Module的屬性設(shè)置進(jìn)來(lái), 而對(duì)使用者,對(duì)部署只需暴露Module對(duì)象即可. 這是以喪失靈活性為代價(jià)的, 替換某個(gè)內(nèi)部對(duì)象的實(shí)現(xiàn)變成了Hack, 需要通過(guò)團(tuán)隊(duì)成員間的交流, 源代碼集體所有來(lái)完成. 如果在Module對(duì)象內(nèi)部枚舉擴(kuò)展點(diǎn)的所有實(shí)現(xiàn), 通過(guò)部署時(shí)的參數(shù)來(lái)挑選某個(gè)實(shí)現(xiàn), 則會(huì)引入不必要的依賴, 更是得不償失

          個(gè)人傾向于第二種. 誰(shuí)介紹一下.Net平臺(tái)上的模塊化框架?



          所以相對(duì)聚焦一點(diǎn), 了解一下IoC框架在處理單個(gè)對(duì)象的時(shí)候所需要解決的問(wèn)題

          1, 部署時(shí)如何方便的支持產(chǎn)品環(huán)境和測(cè)試環(huán)境, 即在不同環(huán)境下提供同一接口的不同實(shí)現(xiàn)


          這個(gè)甚至不需要IoC框架解決, 應(yīng)用開(kāi)發(fā)人員在不同環(huán)境下提供不同配置文件即可. 那問(wèn)題變成了

          2, 如何簡(jiǎn)化配置, 使得框架能夠自動(dòng)識(shí)別依賴


          這個(gè)被稱為Auto wire, 一般根據(jù)構(gòu)造函數(shù)參數(shù)或?qū)傩缘念愋蛠?lái)匹配依賴. 那么帶來(lái)的一個(gè)問(wèn)題是

          3, 運(yùn)行時(shí)如何動(dòng)態(tài)切換同一個(gè)類型的不同實(shí)現(xiàn), 比如用戶選擇了只讀模式, 那么所有的Save操作都應(yīng)被忽略不做任何事, 可以通過(guò)提供Save操作的Dummy版本來(lái)實(shí)現(xiàn)


          Auto wire根據(jù)類型匹配有一定的局限性, 即同一個(gè)運(yùn)行時(shí)環(huán)境有某個(gè)接口的多個(gè)實(shí)現(xiàn)怎么辦.  這里實(shí)際上有一個(gè)概念, 即對(duì)象的標(biāo)識(shí). 而類型只是標(biāo)識(shí)的一種. 另外一種適應(yīng)性更廣的標(biāo)識(shí)是字符串. 有的框架稱之為ID, 有的稱之為name. 標(biāo)識(shí)的重要特征就是在一個(gè)運(yùn)行時(shí)環(huán)境里是唯一的. 類型標(biāo)識(shí)因此也可以轉(zhuǎn)化為字符串標(biāo)識(shí), 取其全名就可以了. (標(biāo)識(shí)本身是個(gè)概念, 可以用一個(gè)類來(lái)表達(dá), 然后有不同的子類實(shí)現(xiàn), 如基于類型的標(biāo)識(shí), 基于字符串的標(biāo)識(shí)等)

          因此就有兩種策略: 一種是允許運(yùn)行時(shí)某個(gè)對(duì)象可以重新聲明依賴的標(biāo)識(shí), 一種是運(yùn)行時(shí)用同樣標(biāo)識(shí)的對(duì)象替換原先的實(shí)現(xiàn). 后一種相對(duì)容易實(shí)現(xiàn)一點(diǎn), 按注冊(cè)順序Last One Win就可以了

          如果同一個(gè)類型的多個(gè)實(shí)例需要同時(shí)存在, 則部署時(shí)給予不同的ID即可. 然而另一個(gè)問(wèn)題是

          4, 多用戶環(huán)境下, 如何保證每個(gè)用戶都有自己的對(duì)象組合而不互相干擾


          IoC框架一般被稱為IoC容器. 容器這個(gè)概念是對(duì)運(yùn)行時(shí)環(huán)境,上下文的封裝, 提供了一組基礎(chǔ)設(shè)施, 以及運(yùn)行時(shí)所需的各種服務(wù), 最重要的一點(diǎn)是, 它提供了在同一個(gè)進(jìn)程里的隔離. 多用戶環(huán)境下, 可以創(chuàng)建多個(gè)彼此獨(dú)立的容器, 每個(gè)容器負(fù)責(zé)創(chuàng)建所需的對(duì)象, 提供所需的服務(wù), 彼此之間互不影響. 于是帶來(lái)新的問(wèn)題,

          5, 對(duì)象的生命周期如何管理


          很顯然, 有的對(duì)象概念上屬于全局, 在程序運(yùn)行過(guò)程中不能創(chuàng)建多個(gè)實(shí)例, 也不能被銷毀. 有的跟用戶的一次操作, 一次請(qǐng)求相關(guān)聯(lián), 同一次請(qǐng)求中可以復(fù)用同一個(gè)對(duì)象實(shí)例, 但不同請(qǐng)求必須創(chuàng)建不同的對(duì)象實(shí)例. 有的則每次需要訪問(wèn)它的時(shí)候都得創(chuàng)建一個(gè)新的實(shí)例. 容器必須提供基礎(chǔ)設(shè)施, 讓?xiě)?yīng)用開(kāi)發(fā)者可以指定對(duì)象的生命周期, 并在周期結(jié)束時(shí)銷毀所有該銷毀的對(duì)象. C# 提供了 Dispose 機(jī)制, 可供利用



          其它的一些問(wèn)題, 比如:

          • 如何支持composite, decorator, proxy模式
          • 如何方便用戶注冊(cè), 包括自動(dòng)注冊(cè)
          • 如何注入容器創(chuàng)建的對(duì)象到用戶手工創(chuàng)建的對(duì)象中
          • 如何與現(xiàn)有各種框架集成
          • 如何避免循環(huán)引用: Constructor/property dependencies
          • Open generics injection
          • List injection    Unregistered resolution
          • Auto-mocking
          • Startable
          • Strongly-typed Activation Events
          • Adding to an Existing Container


          評(píng)論

          # re: IoC 問(wèn)題域  回復(fù)  更多評(píng)論   

          2010-07-12 08:52 by 臨遠(yuǎn)
          目前來(lái)說(shuō),傾向于讓IoC容器只管模塊內(nèi)部的事情,Ioc容器所面對(duì)的:1.自動(dòng)組裝,2.統(tǒng)一aop切面。這種Internal Ioc也可以通過(guò)OSGi的上下文獲取注冊(cè)的服務(wù)。不過(guò)也面對(duì)著一個(gè)問(wèn)題,就是自動(dòng)注冊(cè)的服務(wù)還需要一個(gè)靈活的釋放機(jī)制。

          至于一個(gè)interface多個(gè)implementation的情況,倒是好解決。jsr250里Resource注解里可以指定name,spring提供的Quarified可以指定name,guice里可以用Named標(biāo)示。OSGi可以用filter。實(shí)際上這是一個(gè)前置設(shè)計(jì)的問(wèn)題,提前把可能存在哪些可能的選項(xiàng)都列出來(lái)。

          # re: IoC 問(wèn)題域  回復(fù)  更多評(píng)論   

          2010-07-13 10:28 by anders
          // 部署時(shí)如何方便的支持產(chǎn)品環(huán)境和測(cè)試環(huán)境
          如果說(shuō)模塊是系統(tǒng)的豎切,這里實(shí)際上是個(gè)是系統(tǒng)的橫切,解決方式其實(shí)也很簡(jiǎn)單,預(yù)先讀取當(dāng)前環(huán)境變量,根據(jù)該環(huán)境變量加載同環(huán)境相關(guān)的IoC配置。
          我相信同環(huán)境相關(guān)的IoC配置不會(huì)很多。

          // 運(yùn)行時(shí)如何動(dòng)態(tài)切換同一個(gè)類型的不同實(shí)現(xiàn)
          只能靠代理方式,由代理根據(jù)用戶配置進(jìn)行路由選擇(相當(dāng)于查詢vtable)

          // 多用戶環(huán)境下, 如何保證每個(gè)用戶都有自己的對(duì)象組合而不互相干擾
          也只能靠代理方式,由代理根據(jù)當(dāng)前用戶進(jìn)行路由選擇(相當(dāng)于查詢vtable)

          // 對(duì)象的生命周期如何管理
          可以參考下java的spring,spring核心提供了:singleton和prototype
          spring web提供了request,session,結(jié)合jsf提供了view;spring web flow提供了flash,flow和conversation,可以自定義提供如threadlocal這樣的

          # re: IoC 問(wèn)題域  回復(fù)  更多評(píng)論   

          2010-07-13 22:07 by 切爾斯基
          @anders

          運(yùn)行時(shí)如何動(dòng)態(tài)切換同一個(gè)類型的不同實(shí)現(xiàn), 以及多用戶環(huán)境下, 如何保證每個(gè)用戶都有自己的對(duì)象組合而不互相干擾:

          我們用Autofac, 這兩個(gè)問(wèn)題都是通過(guò)創(chuàng)建 Inner Container 解決的

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 北海市| 安龙县| 海伦市| 枣阳市| 孝感市| 东光县| 集安市| 清丰县| 凌云县| 通海县| 万盛区| 乃东县| 福海县| 大埔区| 灵台县| 武汉市| 肇州县| 宁武县| 新乐市| 尼玛县| 云梦县| 三江| 松滋市| 五大连池市| 本溪市| 临城县| 信阳市| 行唐县| 黑龙江省| 顺义区| 将乐县| 桂平市| 洛隆县| 礼泉县| 静海县| 离岛区| 西藏| 高平市| 城市| 龙胜| 巧家县|