Posted on 2006-11-19 19:59
canonical 閱讀(2737)
評(píng)論(6) 編輯 收藏 所屬分類:
設(shè)計(jì)理論
? 隨著IoC(Inversion of Control)容器的流行,AOP(Apsect Oriented Programming)似乎逐漸成為了主流技術(shù)的一部分,但是除了Transaction, Lazy Load, Cache, Log等少量樣板應(yīng)用之外,AOP的技術(shù)價(jià)值究竟何在? 它能否在廣泛的領(lǐng)域發(fā)揮作用? 為什么考慮到傳統(tǒng)領(lǐng)域之外的應(yīng)用時(shí),我們的想象力是如此的貧乏?回答這些問(wèn)題需要對(duì)AOP的技術(shù)實(shí)質(zhì)作詳細(xì)的審視.
? 傳統(tǒng)上, 程序的結(jié)構(gòu)是靜態(tài)的. 定義了一個(gè)類, 它的成員變量和成員函數(shù)就是確定的了,定義了一個(gè)函數(shù), 它的具體實(shí)現(xiàn)也是確定的. 傳統(tǒng)程序設(shè)計(jì)主要定義了一些固化的規(guī)則來(lái)規(guī)范這些確定性組分的組合關(guān)系,如類繼承體系所表達(dá)的推理關(guān)系. 而AOP是一種動(dòng)態(tài)代碼織入技術(shù), 抽象的說(shuō), 一維拓?fù)涞幕驹厥蔷€段與邊, 而AOP通過(guò)mixin, interceptor等機(jī)制可以自由的實(shí)現(xiàn)這些元素之間的自由組合而不拘泥于預(yù)制的規(guī)則. AOP就像是一把鋒利的砍刀, 我們用它從最終所期望的程序結(jié)構(gòu)中隨意的砍下一部分來(lái), 起個(gè)名字,就叫Aspect吧. 實(shí)際上AOP技術(shù)本身并沒(méi)有限定程序中哪些部分可以作為Aspect, 這種技術(shù)本身并不保證你可以抽象得出真正有價(jià)值的Aspect, 它只是一種純粹的程序結(jié)構(gòu)操縱技術(shù)而已.
? AOP技術(shù)有兩個(gè)主要組成部分: 定位技術(shù)和定位后的組裝技術(shù). 定位技術(shù)是AOP所宣稱的無(wú)侵入性的關(guān)鍵所在. 如果我們使用interface等機(jī)制來(lái)實(shí)現(xiàn)功能,則要在程序各處寫(xiě)下調(diào)用語(yǔ)句:
??? interfaceA.methodA();
??? ...
??? interfaceA.methodB();
這可以看作是一種占位技術(shù). 定位技術(shù)則一般不需要預(yù)先在程序中寫(xiě)下什么調(diào)用語(yǔ)句, 根據(jù)外部的某些定位規(guī)則,我們可以在基礎(chǔ)的程序結(jié)構(gòu)中搜索到適當(dāng)?shù)奈恢? 在理論上說(shuō),這種定位方式非常靈活, 即可以是非常精準(zhǔn)的定位到某個(gè)點(diǎn),也可以是非常寬泛的定位到一組切入點(diǎn). 但是, 這里的一個(gè)隱含假設(shè)是程序基礎(chǔ)結(jié)構(gòu)本身已經(jīng)具備了良好的,具有某種均一性的坐標(biāo)系, 只有這樣我們才能夠擁有定位所需的基本信息. 想象一下,如果整個(gè)程序只有一個(gè)函數(shù), 所有功能的實(shí)現(xiàn)通過(guò)傳入不同的參數(shù)值來(lái)實(shí)現(xiàn), 則這樣的程序結(jié)構(gòu)中是沒(méi)有什么可定位性而言的. 早期AOP定位所能夠依賴的坐標(biāo)只有類,方法名稱, 方法參數(shù)類型等, 而這些信息本身又具有自己的業(yè)務(wù)含義,隨著業(yè)務(wù)的發(fā)展,它們本身的名稱也可能需要不斷的變化,這直接造成AOP所依賴的坐標(biāo)系的不穩(wěn)定性.今天還有效的位置描述, 明天也許就突然包括了某些不應(yīng)該包含進(jìn)來(lái)的程序位置或者排除了某些應(yīng)在其中的位置. 在JDK5.0中補(bǔ)充的annotation機(jī)制為程序補(bǔ)充了新的坐標(biāo)維度, 基于它無(wú)疑可以建立更加靈活而且專用的坐標(biāo)系統(tǒng), 它對(duì)于AOP的價(jià)值必然會(huì)逐漸被發(fā)掘出來(lái). 在javascript這樣的動(dòng)態(tài)語(yǔ)言中,雖然它們內(nèi)置的動(dòng)態(tài)性直接支持程序結(jié)構(gòu)的動(dòng)態(tài)組裝, 但是在定位支持方面卻要比java這樣的語(yǔ)言弱上很多, 在其上建立AOP應(yīng)用未見(jiàn)得比java更具優(yōu)勢(shì). 從另外一個(gè)角度上說(shuō), 定位方式也并不總比占位方式優(yōu)越. 我們需要牢牢記住"一次描述"的優(yōu)勢(shì)在于可以"多次應(yīng)用". 有的時(shí)候我們用很多唇舌去描述一個(gè)物品看起來(lái)像什么什么樣, 有多么大, 多么重, 還不如直接拿給人看, 說(shuō):嘿, 就是這個(gè)(this).同樣在程序中, 占位方式可能更加直接簡(jiǎn)單,甚至因?yàn)榇a明確寫(xiě)在那里,概念也更加明確,更加完整. 此外, 在一些特定的程序結(jié)構(gòu)中, 需要定位的位置大大減少, 我們也不需要復(fù)雜的定位機(jī)制. 例如在witrix的jsplet框架中, 因?yàn)樗厥獾囊?guī)范一致性造成程序的處理點(diǎn)只有一個(gè), 應(yīng)用AOP是一個(gè)非常直接的過(guò)程.
? AOP的第二個(gè)組成部分是組裝技術(shù). 程序結(jié)構(gòu)的組裝在java中早已不是什么技術(shù)難點(diǎn), 很多人干起這活來(lái)都是輕車熟路. 但是組裝不僅僅意味著程序結(jié)構(gòu)的融合, 它同時(shí)意味著程序運(yùn)行時(shí)狀態(tài)空間的融合. 在AOP的基礎(chǔ)模型中, 在切入點(diǎn)可以得到的變量有this指針,調(diào)用函數(shù)對(duì)象和傳入?yún)?shù)列表, 但是AOP本身并沒(méi)有進(jìn)一步規(guī)范化這些變量的具體形式, 因此在一般情況下, 這些變量對(duì)于interceptor來(lái)說(shuō)是只讀的, interceptor之間也無(wú)法通過(guò)這些變量交換信息并協(xié)同運(yùn)行. 這實(shí)際上意味著在切點(diǎn)處inteceptor的狀態(tài)空間是極端受限的. 而當(dāng)一個(gè)切面橫跨很多切點(diǎn)的時(shí)候, 在interceptor中一般只能對(duì)切點(diǎn)處狀態(tài)空間的共性部分進(jìn)行操作, 這進(jìn)一步限制了interceptor的能力.實(shí)際上目前AOP的主要應(yīng)用都是無(wú)狀態(tài)的,或者是基于全局狀態(tài)空間的(例如transaction interceptor只訪問(wèn)線程上下文), 這反映出對(duì)于AOP的primitive方式的應(yīng)用的一種局限性. 在witrix平臺(tái)的BizFlow設(shè)計(jì)中,通過(guò)對(duì)狀態(tài)空間明確建模, 實(shí)現(xiàn)了基于AOP概念的一種新的應(yīng)用方式.
? AOP需要對(duì)程序坐標(biāo)空間和狀態(tài)空間的良好規(guī)劃, 才能保證無(wú)縫的織入, 保證信息交互通道的通暢.應(yīng)用AOP所指的不僅僅是配置使用現(xiàn)有的AOP實(shí)現(xiàn), 基于這種程序結(jié)構(gòu)操控技術(shù)我們所需要做的抽象工作還很多.
?