前言 說起AOP,其實我們在做MVC/API 的時候應該沒少接觸,比如說各種的Fitter 就是典型的AOP了。 本來在使用Polly的時候我最初的打算是使用過濾器來實現的,後來發現實現起來相當的困難,利用NetCore的中間以及過濾器去實現一個AOP的獨立應用服務簡直了,我有點無奈,相當的難寫。 ...
前言
說起AOP,其實我們在做MVC/API 的時候應該沒少接觸,比如說各種的Fitter 就是典型的AOP了。
本來在使用Polly的時候我最初的打算是使用過濾器來實現的,後來發現實現起來相當的困難,利用NetCore的中間以及過濾器去實現一個AOP的獨立應用服務簡直了,我有點無奈,相當的難寫。
後來又使用了,Autofac 做攔截器來實現也是有點小無力。估計還是基礎太薄弱。
目前我瞭解到的實現Polly比較方便的第三方Aop框架的有
(1)、AspectCore:是一款 AspNetCore輕量級的Aop解決方案。
(2)、Dora.Interception 老A寫的一個Aop解決方案,這個用到解決方案中就需要等到老A升級下一版了。
AspNetCore中的過濾器:
在使用Policy 的時候主要點是策略的制定,在保證代碼整潔,並且不破壞當前代碼邏輯的情況下,使用Aop是最合適的解決方案了。
當我們使用過濾器的時候我們會發現,Pollicy 制定了一個錯誤規則,並且在錯誤過濾器中使用、抓取不到任何的錯誤信息,因為錯誤信息被錯誤過濾器抓取了,這個時候不會觸發Pollicy
然後嘗試著 用過濾實現一個 當程式發生錯誤的時候,執行另一個方法的功能,類似Policy的重試策略或降級。
下麵代碼:
編寫:一個過濾器類:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Reflection; namespace InterceptorCoreLibrary { [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)] public class CoreExceptionFilter:Attribute, IExceptionFilter,IActionFilter { /// <summary> /// 發生錯誤的時候重新執行的方法 /// </summary> public string FallBackClass { get; set; } /// <summary> /// 發生錯誤的時候重新執行的方法 /// </summary> public string FallBackMethod { get; set; } /// <summary> /// 獲取方法的參數 /// </summary> public object[] InvokeParameters { get; set; } /// <summary> /// 構造函數使用該類時參數為方法 /// </summary> /// <param name="fallBackMethod"></param> public CoreExceptionFilter(string fallBackClass, string fallBackMethod) { this.FallBackMethod = fallBackMethod; this.FallBackClass = fallBackClass; } /// <summary> /// 使用新方法 /// </summary> /// <param name="asm"></param> /// <param name="parameters"></param> /// <returns></returns> private object UseNewMethod(Assembly asm, object[] parameters) { Object obj = null; foreach (Type type in asm.GetExportedTypes()) { if (type.Name == FallBackClass) { obj = System.Activator.CreateInstance(type); foreach (var item in type.GetMethods()) { if (item.Name == FallBackMethod) { obj = type.GetMethod(FallBackMethod).Invoke(obj, parameters); } } } } return obj; } /// <summary> /// 獲取所有被監控方法的參數 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { object[] parameters = new object[context.ActionArguments.Count]; int Count = 0; foreach (var item in context.ActionArguments) { parameters[Count] = item.Value; Count++; } InvokeParameters = parameters; } /// <summary> /// 錯誤的時候執行新的方法 /// </summary> /// <param name="context"></param> public void OnException(ExceptionContext context) { var objectResult = context.Exception as Exception; if (objectResult.Message != null) { //context.Result = new ObjectResult(UseNewMethod(this.GetType().Assembly, InvokeParameters)); context.Result = new ObjectResult(new { Success = true, code = 200, msg = "成功", Data = UseNewMethod(this.GetType().Assembly, InvokeParameters) }); } } public void OnActionExecuted(ActionExecutedContext context) { } } }
在控制器中使用:
[CoreExceptionFilter(nameof(UserModel), nameof(Delete))] 在執行的時候我拋送一個異常信息 [CoreExceptionFilter(nameof(UserModel), nameof(Delete))] // DELETE api/values/5 [HttpDelete("{id}")] public int Delete(int id) { throw new Exception(); }
當方法執行出錯的時候執行另一個方法:
如下:註意參數一致:
using System; using System.Collections.Generic; using System.Text; namespace InterceptorCoreLibrary { public class UserModel { public int Delete(int id) { //記錄日誌 //重新執行一遍代碼 return id; } } }
執行結果:
返回結果:
這個時候我們能看到過濾器先抓取了錯誤信息,Policy 就抓不到了,但同樣實現了降級的功能。
如果我們不使用Aop的話 直接在控制器中寫
比如:這樣寫一個兩個還行多了的話,代碼就相當的亂了。
// DELETE api/values/5 [HttpDelete("{id}")] public int Delete(int id) { var PolicyExecute = Policy.Handle<Exception>().Fallback(() => { //程式報錯重新執行一個新的方法 UserModel userModel = new UserModel(); userModel.Delete(id); }); //執行 PolicyExecute.Execute(() => { throw new Exception(); } ); }
以上代碼雖然沒有實現policy ,但是也演示出了大致使用Aop實現 Policy的過程原理。
使用AspectCore 實現Policy
這裡貼出一份楊中科老師 在普及AspNetCore微服務課程中的代碼:支持原創,
完整的代碼這裡貼出過:
http://www.cnblogs.com/qhbm/p/9228238.html
使用Dora.Interception 實現Policy
我在Demo中進行了簡單的實現:這裡就不貼出了,因為框架還不是很完善,我問了作者老A,要等到下一版出來後用在項目中才比較穩妥。大家可以關註一下老A博客。
截圖說明一下兩個框架的區別,到時候可根據框架需要酌情使用:
有不足之處 希望大家指出相互學習,
本文原創:轉載請註明出處 謝謝!