??在.NET中要實(shí)現(xiàn)AOP有多種辦法晚树,至少包含如下幾種:
- 微軟企業(yè)庫Microsoft Enterprise Library
- postsharp(收費(fèi))
- ContextBoundObject
- Castle.Core
- Remoting的RealProxy
- ...
對(duì)于第一種解藻,需要安裝較大的類庫,第二種收費(fèi)牢屋,因此這兩者使用相對(duì)沒那么多,本文只比較后面三種的性能情況跨释。
先看結(jié)果
三種方法分別使用AOP和非AOP得方式調(diào)用相同空方法1000000次的結(jié)果如下:
ContextBoundObject | Proxy | Castle | |
---|---|---|---|
Original: | 5399 | 4 | 4 |
Aop: | 8420 | 1456 | 48 |
可以看出窗宇,性能差距是巨大的,為什么有這么大的差距呢侦另?接下來分析一下原理秩命。
ContextBoundObject
通過ContextBoundObject來實(shí)現(xiàn)AOP,其中有大約60%的時(shí)間花在GetCustomAttribute的反射上褒傅,另外40%則是MarshalByRefObject(ContextBoundObject的基類弃锐,實(shí)際上ContextBoundObject什么事情都沒做,只是單純的繼承了MarshalByRefObject)內(nèi)部上下文管理上殿托,它需要管理些啥呢拿愧?ContextBoundObject是一個(gè)上下文對(duì)象的基類,繼承自它的子類將被一個(gè)特別的上下文管理起來碌尔,這個(gè)上下文包括一系列的屬性集合或者規(guī)則,當(dāng)進(jìn)入或者離開上下文時(shí)券敌,將強(qiáng)制執(zhí)行規(guī)則唾戚。當(dāng)使用ContextBoundObject實(shí)現(xiàn)AOP時(shí),除了性能底下待诅,其必須繼承自ContextBoundObject叹坦,對(duì)于單繼承的語言來講可能帶來不便。
Proxy
Proxy實(shí)現(xiàn)AOP會(huì)利用到RealProxy和TransparentProxy卑雁,它們分別是干啥的呢募书?
TransparentProxy:在 CLR 中在 IL 層面最大程度扮演被代理的遠(yuǎn)端對(duì)象绪囱,從類型轉(zhuǎn)換到類型獲取,從字段訪問到方法調(diào)用莹捡。對(duì) CLR 的使用者來說 TP 和被其代理的對(duì)象完全沒有任何區(qū)別鬼吵,只有通過 RemotingServices.IsTransparentProxy 才能區(qū)分兩者的區(qū)別。
RealProxy:是提供給 CLR 使用者擴(kuò)展代理機(jī)制的切入點(diǎn)篮赢,通過從 RP 繼承并實(shí)現(xiàn) Invoke 方法齿椅,用戶自定義代理實(shí)現(xiàn)可以自由的處理已經(jīng)被從棧調(diào)用轉(zhuǎn)換為消息調(diào)用的目標(biāo)對(duì)象方法調(diào)用,如實(shí)現(xiàn)緩存启泣、身份驗(yàn)證涣脚、安全檢測(cè)、延遲加載等等寥茫。
使用Proxy來實(shí)現(xiàn)AOP其消耗主要來自TP和RP兩個(gè)對(duì)象的實(shí)例化以及“對(duì)象引用 -> TP -> RP -> 實(shí)際對(duì)象”的調(diào)用鏈遣蚀。
Castle
Castle的本質(zhì)是創(chuàng)建繼承原來類的代理類,重寫虛方法實(shí)現(xiàn)AOP功能纱耻。內(nèi)部通過大量的Reflect.Emit + OpCode編程來實(shí)現(xiàn)高性能的保證芭梯,可以在很多開源項(xiàng)目中找到Castle的身影。