其實說起AOP,我在2011年的時候就發過一個帖子,CSDN的地址為http://bbs.csdn.net/topics/370067862,只是那時候對EMIT了解的深度不夠,所以內容顯得有些稚嫩,但對於我來說,意義很大。從那個時候開始起我算對EMIT入門了。
不扯遠了,回到正題上來。AOP的實現方式是分2種的,一種是繼承式的,這種實現的方式需要注入的方法上打上virtual,這樣子類才能繼承並重寫它,如下圖所示:
第二種就是代理式的,代理式的注入一般是需要有抽象的接口的,其大致的實現原理如下圖所示:
而本文所使用的方式就是第二種,這里可能有的童鞋有疑問了,為啥呢?這里說明一下,在方法內部的EMIT代碼的植入上其實沒什么區別,只是第一種方式只需要重寫帶virtual的方法即可,在EMIT上而言,較為簡單,並且在2011年的那個帖子的實現方式就是基於第一種,所以這次想換條路走走。而第二種是需要一個對接口實現的過程,難度稍微大一些,從學習的角度,自然也是最佳的選擇。
說到這里只交代了正題的一半,那另一半是怎么回事呢?剛才已經把代理式的AOP的原理大致的說了一下,最終會動態的創建一個實現了某個接口的類,既然費勁的創建了一個新類,那肯定就是要使用它來做事情,做事情的第一步是什么呢?對拉,就是new一個實例。這時候懶人(例如我)就說了,這一個個的new多費勁,而且代碼顯得很low,想高大上?這時候你是不是想到了IOC或者DI呢(這倆名詞不理解的童鞋可自行BAIDU),是的,可以。但一想到自己一個小小的項目要引一堆的dll,而且還用不到里面的幾個方法,於是我創造輪子的想法又蹦出來了,當前這個不能跟各種IOC框架或者DI框架比,不是一個量級,也比不上人家完美,但對於我來說,就僅僅需要它自動裝配即可,夠用就好。於是在實現了AOP的基礎上,自動裝配的代碼也開動了。。。
原理上我們大概了解了,剩下的就是動手了,而動手其實就是燒腦的過程,各種頭疼的IL指令,為了不讓各位童鞋也頭疼或者看的費勁,這里面的過程我就不做詳細的解釋了,貼幾個能展現部分邏輯的重要代碼段:
最后我想通過一些測試的代碼來展示一下這個東西的最終的效果,如果有想研究EMIT的童鞋,可根據我代碼里面的注釋,以及各種IL指令去理解和嘗試一下自己創造一個輪子。
測試代碼中測試了AOP的三種攔截方式:
1、一般攔截,在方法執行的前后,各執行一段代碼
2、認證攔截,只有通過了認證接口后,才能正常的調用代理類的方法
3、異常攔截,在出現異常時,進行異常的捕獲與處理
對測試類打的標記如下圖所示:
寫的測試例子:
運行的結果:
寫到這里也就結束了,由於文采有限,只是把我想說的重點,表述了一下,大部分的內容都是貼圖,可能有部分的童鞋看的不習慣,還請輕噴,謝謝。
關於版權,由於我的知識來自互聯網,可以說,沒有互聯網,就沒有現在的我,甚至就沒我現在的飯碗,本着感恩的心,誠摯的回饋。所以我這里的代碼是完全公開的,不涉及版權,您可以隨便用(如果您對本源碼有改造或者擴展,而且您願意與大家一起分享的話,我將不勝感激),但因此而產生的各種后果也請您自行承擔。如果您要轉載本文,還請您保留原文的地址,謝謝。
源碼地址:http://download.csdn.net/detail/nqicecoffee/9592036
=======================================2016年8月3日更新===============================================
經過高人 @時光之后 指點后,修正了2處問題:
1、修復屬性的植入邏輯
2、優化初始化結果的IL指令
源碼地址:http://download.csdn.net/detail/nqicecoffee/9593358