.Net core+Reds如何實現Aop緩存
前言
在實際開發的場景中,有很多需要緩存的數據,為了減少重復代碼的編寫,想采用Aop的方式來實現切面編程減少對以有業務代碼的改動和侵入性。
在傳統的 .Net Framework項目中實現Aop有很多簡單的方式,但是在 .Net Core中尤其是1.X版本筆者沒有找到比較好的解決方案采用了一個三方開源的Aop庫,下面會寫出來。
准備
本次采用的環境是 .Net Core 1.1版本
本次使用的Aop 開源庫是 AspectCore 0.1.2版本
實踐
Aop顧名思義面向切面編程,是一種通過預編譯和運行時動態代理來實現的一種技術,本文中采用了三方開源的Aop庫 AspectCore 是.Net Core 中一個輕量級和模塊化的Aop 解決方案
首先創建一個 緩存特性 CacheAttribute 繼承 AspectCore中的 InterceptorAttribute並且重寫 InterceptorAttribute中的 Invoke方法 代碼 如下
1 public async override Task Invoke(AspectContext context, AspectDelegate next) 2 { 3 try 4 { 5 //用方法名稱+入參 生成Key 6 string key = context.Proxy.ProxyMethod.Name; 7 foreach (var item in context.Parameters) 8 { 9 key += item.Value; 10 } 11 //判斷緩存是否已經存在 12 var isExists = await RedisCache.ExistsAsync(key); 13 if (!isExists) 14 { 15 //如果不存在緩存 則執行方法 並且緩存方法返回值 16 await next(context); 17 await RedisCache.SetAsync(key, JObject.FromObject(context.ReturnParameter.Value).ToString(), Timeout); 18 } 19 else 20 { 21 var result = RedisCache.Get(key); 22 if (_type != null) 23 { 24 //判斷是否異步返回類型 因為異步方法無法正常轉換 需要先取返回后 在異步化 25 dynamic info = JObject.Parse(result).ToObject(_type); 26 context.ReturnParameter.Value = Task.FromResult(info.Result); 27 } 28 else 29 context.ReturnParameter.Value = JObject.Parse(result).ToObject(context.ReturnParameter.ParameterType); 30 } 31 } 32 catch (Exception ex) 33 { 34 //Aop異常 直接跳過Aop 進入方法 35 await next(context); 36 } 37 }
上面的代碼展示了 如何使用AspectCore結合Redis實現Aop緩存,在實現的過程中筆者發現,異步方法沒有辦法通過Json正常的轉換,所以先通過取值在進行異步化,如果有哪位大神有好的解決方案還請告知一二(十分感謝),同步方法沒有問題可以正常Json和轉換。
實現了核心的Aop的代碼最后使用的時候 很簡單代碼如下幾種情況
1.同步方法
1 public interface ITestService 2 { 3 [Cache] 4 Test Show(); 5 }
2.異步方法
1 public interface ITestService 2 { 3 [Cache(typeof(Parameter<Test>))] 4 Task<Test> Show(string input); 5 }
只要在接口的方法上標上Cache 特性即可實現對現有業務無入侵的改造
思考
在這次實現Aop 的過程中,筆者一直有個疑問在Aop緩存的實現中,通過緩存整個方法的返回是不是一個好的解決方案,在一些特殊的業務場景中如果這個方法返回是一個復雜的類型 是否會有異常?如果不通過緩存整個方法返回 是否還有什么更好的解決方案? 如果各位大神有更好的解決方案,還請多多指教,現在這里感謝了。