AOP面向切面編程(Aspect Oriented Programming),是通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。
實現AOP主要由兩種方式,一種是編譯時靜態植入,優點是效率高,缺點是缺乏靈活性,.net下PostSharp為代表者(這個是收費的)。
另一種方式是動態代理,優缺點與前者相反,動態為目標類型創建代理,通過代理調用實現攔截。
Spring框架用的核心技術就是AOP,是函數式編程的一種衍生范型。利用AOP的好處就是可以對業務邏輯進行隔離,降低耦合度,提高程序的可重用性,同時提高了開發的效率。
AOP在我理解來說就是一種編程思想和架構設計,AOP是OOP面向對象編程的延續,是軟件開發中的一個熱點。AOP的簡稱叫”面向切面“編程,即在現有的代碼里橫向的切分開來進行相應處理,比如說MVC里的刷選器(過濾器)。
AOP主要功能是將系統中非核心的公共業務提取出來,進行單獨處理。比如日志記錄、性能統計、安全控制、事務處理、異常處理等等。
AOP主要意圖是將日志記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中划分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的代碼。
下面介紹一些.NET相關的AOP框架
1. PostSharp(編譯時靜態植入)是最有名且使用率較高的一個,但是在Nuget上的版本是需要付費的(2.0)以上都要付費。
2. Spring.Net 用於解決企業應用開發復雜性的一種容器框架,它實現了控制反轉IOC和依賴注入DI,通俗解釋就是通過spring.net框架的容器來創建對象實體,而不是通過程序員new出來,
降低程序對服務類的依賴性,提高軟件的可擴展性。只要在spring.net的相應xml中配置節點,創建容器上下文后再通過配置獲取對象就可以。
3. Autofac 是一個.net下非常優秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP簡直是如虎添翼。Autofac的AOP是通過Castle(也是一個容器)項目的核心部分實現的,名為Autofac.Extras.DynamicProxy,
顧名思義其實現方式為動態代理。
4. Castle.Core 本質是創建繼承原來類的代理類,重寫虛方法實現AOP功能。
5. KingAOP 開源框架KingAOP是基於動態類型進行操作和綁定的。
個人推薦使用Castle.Core 或者 KingAOP
下面介紹一個比較精簡的AOP框架:KingAOP 使用方式比較簡單,如下順序:
1、在Nuget上搜索KingAOP,如圖:
或者通過命令安裝:
Install-Package KingAOP
2、創建一個刷選器類(切面處理類),繼承OnMethodBoundaryAspect,並重寫相關的事件,如下代碼:
/// <summary> /// 創建一個刷選器類(切面處理類) /// </summary> public class AopFilter : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnEntry"); base.OnEntry(args); } public override void OnException(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnException"); base.OnException(args); } public override void OnSuccess(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnSuccess"); base.OnSuccess(args); } public override void OnExit(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnExit"); base.OnExit(args); } }
3、創建一個類,該類的方法注冊上面新建的刷選器,如下代碼:
/// <summary> /// 該類需要繼承IDynamicMetaObjectProvider,因為KingAOP是基於動態類型進行操作和綁定的,如不繼承是不會進入到刷選器中的相應事件里 /// </summary> public class SimonDemo : IDynamicMetaObjectProvider { public SimonDemo() { Console.WriteLine(" Call 'SimonDemo類' - 'Constructor(構造函數)'"); } [AopFilter] public void Operate() { Console.WriteLine("Call 'SimonDemo類' - 'Operate方法' "); } /// <summary> /// 該類必須實現IDynamicMetaObjectProvider的GetMetaObject方法 /// </summary> /// <param name="parameter"></param> /// <returns></returns> public DynamicMetaObject GetMetaObject(Expression parameter) { return new AspectWeaver(parameter, this); } }
上面的SimonDemo類需要繼承IDynamicMetaObjectProvider,因為KingAOP是基於動態類型進行操作和綁定的,如不繼承是不會進入到刷選器中的相應事件里。
該類必須實現IDynamicMetaObjectProvider的GetMetaObject方法,同時在需要切面的方法上用屬性[AopFilter]進行標注,
同時,刷選器屬性是限制了只能對應方法,且不包含構造函數;
4、接下來就是測試代碼,如下
static void Main(string[] args) { //簡單例子 Console.WriteLine("Call Main .."); //注意:如果需要用KingAop進行橫向切面則必須在實例化被切面的類時用動態類型dynamic接收 dynamic simon = new SimonDemo(); simon.Operate(); Console.WriteLine("exit Main .."); Console.Read(); }
上面的代碼執行后是這個樣子的,如下圖:
仔細看代碼SimonDemo是以動態類型 dynamic來接收的,我們把代碼改成SimonDemo simon = new SimonDemo();后執行會怎么樣?如下圖:
實踐后發現,如果需要用KingAop進行橫向切面則必須在實例化被切面的類時用動態類型dynamic接收。
整體而言,這個框架還是挺簡單的