程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Emit學習-實戰篇-實現一個簡單的AOP框架(一)

Emit學習-實戰篇-實現一個簡單的AOP框架(一)

編輯:關於.NET

周末兩天窩在家裡,使用Emit做了一個非常簡單的AOP框架,當做是這幾周學習Emit後的一個實踐。東西出來了,自然要和大家分享一下,雖然框架做的比較粗糙、簡單,但是也已經能夠看到一點AOP的雛形了,用來自己無聊玩玩還是可以的,當然要用到產品中去肯定還需要長期的完善啦。

說起AOP相信園子裡很多高手都研究過,園子裡好像也有自己的開源AOP項目,不過我時間有限沒有細找,同時也發現園子研究AOP理論方面的文章很多,但是好像並沒有完整的實現一個簡單AOP框架的例子(當然我只是簡單的找了一下,如有遺漏懇請諒解。),正好趁這個機會寫一個這方面的例子,能夠讓像我這樣的菜鳥對AOP有更多的了解。

有關AOP的概念介紹,網上有非常多的解釋,我也沒有時間一一細看,這裡給出百度百科中的解釋:

面向方面編程:Aspect Oriented Programming

AOP是OOP的延續,是Aspect Oriented Programming的縮寫,意思是面向切面編程。可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP可以說也是這種目標的一種實現。

舉例:假設有在一個應用系統中,有一個共享的數據必須被並發同時訪問,首先,將這個數據封裝在數據對象中,稱為Data Class,同時,將有多個訪問類,專門用於在同一時刻訪問這同一個數據對象。

為了完成上述並發訪問同一資源的功能,需要引入鎖Lock的概念,也就是說,某個時刻,當有一個訪問類訪問這個數據對象時,這個數據對象必須上鎖Locked,用完後就立即解鎖unLocked,再供其它訪問類訪問。

使用傳統的編程習慣,我們會創建一個抽象類,所有的訪問類繼承這個抽象父類,如下:

abstract class Worker{

         abstract void locked();

         abstract void accessDataObject();

         abstract void unlocked();

   }

缺點:

accessDataObject()方法需要有“鎖”狀態之類的相關代碼。

Java只提供了單繼承,因此具體訪問類只能繼承這個父類,如果具體訪問類還要繼承其它父類,比如另外一個如Worker的父類,將無法方便實現。

重用被打折扣,具體訪問類因為也包含“鎖”狀態之類的相關代碼,只能被重用在相關有“鎖”的場合,重用范圍很窄。

仔細研究這個應用的“鎖”,它其實有下列特性:

l “鎖”功能不是具體訪問類的首要或主要功能,訪問類主要功能是訪問數據對象,例如讀取數據或更改動作。

l “鎖”行為其實是和具體訪問類的主要功能可以獨立、區分開來的。

l “鎖”功能其實是這個系統的一個縱向切面,涉及許多類、許多類的方法。如下圖:

因此,一個新的程序結構應該是關注系統的縱向切面,例如這個應用的“鎖”功能,這個新的程序結構就是aspect(方面)

在這個應用中,“鎖”方面(aspect)應該有以下職責:

提供一些必備的功能,對被訪問對象實現加鎖或解鎖功能。以保證所有在修改數據對象的操作之前能夠調用lock()加鎖,在它使用完成後,調用unlock()解鎖。

AOP應用范圍

很明顯,AOP非常適合開發J2EE容器服務器,目前JBoss 4.0正是使用AOP框架進行開發。

具體功能如下:

l Authentication 權限

l Caching 緩存

l Context passing 內容傳遞

l Error handling 錯誤處理

l Lazy loading 懶加載

l Debugging 調試

l logging, tracing, profiling and monitoring 記錄跟蹤 優化 校准

l Performance optimization 性能優化

l Persistence 持久化

l Resource pooling 資源池

l Synchronization 同步

l Transactions 事務

AOP有必要嗎

當然,上述應用范例在沒有使用AOP情況下,也得到了解決,例如JBoss 3.XXX也提供了上述應用功能,但是沒有使用AOP。

但是,使用AOP可以讓我們從一個更高的抽象概念來理解軟件系統,AOP也許提供一種有價值的工具。可以這麼說:因為使用AOP結構,現在JBoss 4.0的源碼要比JBoss 3.X容易理解多了,這對於一個大型復雜系統來說是非常重要的。

從另外一個方面說,好像不是所有的人都需要關心AOP,它可能是一種架構設計的選擇,如果選擇J2EE系統,AOP關注的上述通用方面都已經被J2EE容器實現了,J2EE應用系統開發者可能需要更多地關注行業應用方面aspect。

看了上面的內容,相信大家也跟我一樣對AOP有了一個大致的了解,接下來就對我們的AOP框架要實現的功能進行界定。

首先,我們將一個方法的執行分成為如下幾個部分:

l 調用前的預處理:可以包括日志記錄、權限控制、驗證安全性等;

l 真正的方法體調用;

l 調用後的處理:可以包括事後的日志記錄、持久化調用結果等;

l 套在前面3個部分外面的異常處理程序。

這樣,我們就把要關注的切面分成了3類:調用前處理、調用後處理以及異常處理。我們通過屬性+接口+配置文件的方式來完成開發人員對這些切面的定義及使用。這裡先給出一個客戶端的方法中的使用示例,其它的就等下次再講吧,明天還得早起,得洗洗睡了。

public class Test
{
     [Aspect(AspectTypes.PreProcess | AspectTypes.ExceptionHandler)]
     public virtual void Test1(string num)
     {
         Console.WriteLine(Convert.ToInt32(num));
     }

     [Aspect(AspectTypes.PostProcess | AspectTypes.ExceptionHandler)]
     public virtual int Test2(string num)
     {
         return Convert.ToInt32(num);
     }

     [Aspect(AspectTypes.ExceptionHandler)]
     public virtual int Test3(string num)
     {
         return Convert.ToInt32(num);
     }
}

可以從三個切面中選擇自己需要的進行處理,和Aspect這個屬性對應的還有一份配置文件,每個方法可以選擇自己的處理程序,也可以使用默認的處理程序。

在具體的使用時,只要按照下面的方法創建一個動態代理類即可,非常的簡便,如下:

Test test = DynamicProxyFactory.CreateProxy<Test>(typeof(Test));

好啦,偶先閃了!~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved