MVC AOP面向切面編程
AOP這個詞相信大家都沒有接觸太多過,但是實際上你們已經有所接觸了,就在設計模式中。 AOP所用的思想其實和設計模式是一樣的,即在不修改原代碼的情況下統一增加或者修改功能。還有,AOP大多用在spring裡面,但是本文所寫的只是在MVC中的應用,要注意。
一、簡介
所謂AOP(Aspect Oriented Programming的縮寫)意為面向切面的編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。 AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
以上是百度百科的官方解釋,但是在我看來,其實AOP更多的是一種思想,一種可以動一發而通全身的思想,AOP其實面對的更多是一種同意的功能或者調用過程來進行編寫的一種程序體,從它的第一個詞Aspect(切面)也就是指的一個方面,也可以了解到這種方式也就是針對一個方面的實現,這一點其實和mvc中的global文件很像,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
其次就是它的預編譯性質可以很好的處理一些錯誤或者是預先判斷一些情況,這也導致了它在設計的時候在判斷權限,統一輸出某個東西方面變得比較常見。 “可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,提高代碼的靈活性和可擴展性,AOP可以說也是這種目標的一種實現。”上面這句話也是對於AOP的很好的詮釋。
二、在MVC中的實現
說了這麼多了,讓我們來實戰一下吧,首先我們需要在vs新建一個mvc的項目,選擇MVC3或者是4都OK,然後建立一個controller,命名隨意,然後建立他的視圖,在視圖上寫上最簡單的HelloWorld。
<!DOCTYPE html> <html> <head> <title>Index</title> </head> <body> <div> <a>Hello! World</a> </div> </body> </html>
右圖是我創建好的MVC解決方案和添加好的controller還有view,在view中寫入上面的代碼以顯示Hello! World。
運行之後(不會運行的自行百度)是不是就顯示出了一個HelloWorld的字樣在網頁上呢?
好,接下來我們開始新建AOP的一個文件然後去使用,首先在本項目中新添加一個類,名字叫FilterPublic,在引用的地方添加using System.Web.Mvc這個引用,然後讓這個類繼承於ActionFilterAttribute,大家要注意Action這個詞,說明這個東西是基於動作的。
然後我們寫入以下代碼:
public string Message { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); filterContext.HttpContext.Response.Write("Action執行之前" + Message + "<br />"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); filterContext.HttpContext.Response.Write("Action執行之後" + Message + "<br />"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { base.OnResultExecuting(filterContext); filterContext.HttpContext.Response.Write("返回Result之前" + Message + "<br />"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { base.OnResultExecuted(filterContext); filterContext.HttpContext.Response.Write("返回Result之後" + Message + "<br />"); }這個里面就是Filter觸發的各種動作,然後我們在controller裡面的默認方法做以下修改:
[<span style="font-size:18px;">FilterPublic</span>(Message = "Action")] public ActionResult Index() { HttpContext.Response.Write("Action正在執行・・・<br />"); return Content("正在返回Result・・・<br />"); }然後在controller的class類上面也添加一句[FilterPublic(Message = "Controller")],然後運行,會出現什麼結果呢?
Action執行之前Action Action正在執行・・・ Action執行之後Action 返回Result之前Action 正在返回Result・・・ 返回Result之後Action
可以看到controller裡面的方法在執行之前會去先執行以下我們設置的FilterPublic裡面的代碼,而且隨著裡面動作發生時間不同也可以看出了都是哪個方法被觸發了。
但是在controller上面寫的基於controller的方法卻沒有觸發,這是為什麼呢?
其實這個問題很簡單,就是我們在設置我們的AOP程序的時候沒有進行參數的設置,沒有讓filter進行疊加的運行,這個時候我們只要在寫的FilterPublic類的上面加上:[AttributeUsage(AttributeTargets.All, AllowMultiple = true)],就可以讓你設置的各種filter或者疊加的filter進行觸發了,這個時候我們再運行一下試試:
Action執行之前Controller Action執行之前Action Action正在執行・・・ Action執行之後Action Action執行之後Controller 返回Result之前Controller 返回Result之前Action 正在返回Result・・・ 返回Result之後Action 返回Result之後Controller
這樣一來,在controller上的Filter也被觸發了,所以我們使用AOP的方法只需要在我們自己的寫的方法或者頁面默認的加載方法上面寫上一個filter類的標籤就可以了。
那麼,如果我們有個功能需要所有的頁面都觸發,這樣豈不是也很麻煩麼?別擔心,這個時候就輪到我們的global文件發揮作用了。在global.asax文件下面的RegisterGlobalFilters方法下面註冊自己寫的Filter就可以了:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); //把自己的filter定義成全局的filter filters.Add(new <span style="font-size:18px;">FilterPublic</span>() { Message = "全局<br/>" }); }然後運行,看結果:
Action執行之前全局Action執行之前Controller Action執行之前Action Action正在執行・・・ Action執行之後Action Action執行之後Controller Action執行之後全局返回Result之前全局返回Result之前Controller 返回Result之前Action 正在返回Result・・・ 返回Result之後Action 返回Result之後Controller 返回Result之後全局
這樣全局的觸發也就做好了(filter中的message只是用於標識層級的,正式用的時候可以不用定義。)
這樣一看,如果想要快速的添加一個全局都用的方法,只需要新建一個Filter,然後再改一下global文件就可以辦到了,是不是很方便呢。
以上均為本人對於AOP的一些淺淺的研究,如有錯誤的地方還請讀者指正。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!