AOP(面向切面编程)大概了解一下
前言
上一篇在聊MemoryCache的時候,用到了Autofac提供的攔截器進行面向切面編程,很明顯能體會到其優勢,既然涉及到了,那就趁熱打鐵,一起來探探面向切面編程。
正文
1. 概述
在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期間動態代理實現程序功能統一維護的一種技術。AOP是OOP(面向對象程序設計)的延續,是軟件開發中的一個熱點,是函數式編程的一種衍生范型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
---來自百度百科
總結優點
對業務邏輯的各個部分進行隔離,業務之間耦合度降低;
提高程序的可重用性,同時程序更容易維護;
提高開發效率,不用花大量的時間在業務中增加代碼,還能降低風險;
其實AOP的本質就是動態代理,何為動態代理呢?
動態代理就是在程序運行時,創建目標對象的代理對象,并對目標對象中的方法進行功能性增強的一種技術。通俗一點來說就是在運行期間對方法的攔截,在方法執行前后進行額外的業務處理,從而在不嵌入原有代碼邏輯情況下就能增強被攔截方法的業務能力。
理論先到這,一起來看看用代碼怎么實現吧?
2. 實踐檢驗真理(到底優不優秀)
先來一個控制臺項目,什么都沒有,從頭開始擼代碼,先來看看項目結構:
老案例了,還是假裝在進行用戶維護,模擬對用戶進行增刪改查。這次就直接上代碼啦啊,根據項目結構依次看看代碼:
在AopModel中增加User.cs
public?class?User {public?string?Name?{?get;?set;?}public?int?Age?{?get;?set;?} }在AopService中增加IUser.cs和User.cs
IUserService.cs
public?interface?IUserService {bool?AddUser(User?user); }UserService.cs
public?class?UserService?:?IUserService {public?bool?AddUser(User?user){Console.WriteLine("用戶添加成功");return?true;} }Main方法
class?Program {static?void?Main(string[]?args){Console.WriteLine("========原始需求=========");User?user?=?new?User?{?Name?=?"Zoe",?Age?=?18?};IUserService?userService?=?new?UserService();//?模擬增加一個用戶userService.AddUser(user);Console.ReadLine();} }
這樣項目就正常運行啦,這個就不用我截圖了吧,小伙伴都會吧。
項目運行正常,但需要加一個需求:用戶增加成功之后進行郵件發送通知。
目前有兩種解決方案
直接在增加用戶方法中添加加發送郵件邏輯(相信很多小伙伴是這樣做的,見效快,還簡單);
如果頻繁在增加用戶前或后添加新需求呢,還繼續加嗎,可能到最后增加用戶的方法變得很復雜,后期也不好維護;如果要去掉某一個功能,又得把代碼改回來,作為程序員是不是又要和產品同事搞架啦(文明人,不動手);當然,如果需求固定,這種方式也不錯。
面向切面實現,即在不影響原有代碼邏輯的情況,動態的對方法進行攔截,在方法執行前或后添加業務即可。
項目中引入AOP(面向切面編程)思想
原始動態代理實現;
先來加個代理類,如下:
using?System; using?System.Collections.Generic; using?System.Reflection; using?System.Text; namespace?Aop {//?繼承DispatchProxypublic?class?MyProxy?:?DispatchProxy{//具體類型public?object?TargetClass?{?get;?set;?}protected?override?object?Invoke(MethodInfo?targetMethod,?object[]?args){Console.WriteLine("增加用戶前執行業務");//調用原有方法targetMethod.Invoke(TargetClass,?args);Console.WriteLine("增加用戶后執行業務");return?true;}} }然后在Main函數直接使用即可,如下:
class?Program {static?void?Main(string[]?args){//原始需求User?user?=?new?User?{?Name?=?"Zoe",?Age?=?18?};IUserService?userService?=?new?UserService();userService.AddUser(user);Console.WriteLine("========動態代理?實現新需求=========");//1.?創建代理對象IUserService?userService1?=?DispatchProxy.Create<IUserService,?MyProxy>();//2.?因為調用的是實例方法,需要傳提具體類型((MyProxy)userService1).TargetClass?=?new?UserService();userService1.AddUser(user);Console.ReadLine();} }動態代理就實現需求功能啦,可以在用戶增加前或后都進行相關需求處理,運行看效果:
第三方庫Castle.Core封裝的美滋滋;
通過上面演示,原生的動態代理實現面向切面編程顯得相對麻煩,比如強制轉換、傳遞類型等操作;常用的Castle.Core將動態代理進一步封裝,使用就相對方便點啦;這次定義一個攔截器即可:
using?Castle.DynamicProxy; using?System; using?System.Collections.Generic; using?System.Text;namespace?Aop {//?自定義攔截器public?class?MyIntercept?:?IInterceptor{public?void?Intercept(IInvocation?invocation){//執行原有方法之前Console.WriteLine("增加用戶前執行業務");//執行原有方法invocation.Proceed();//執行原有方法之后Console.WriteLine("增加用戶后執行業務");}} }Main函數中使用攔截器即可,如下:
using?AopModel; using?AopService; using?Castle.DynamicProxy; using?System; using?System.Reflection; using?System.Reflection.Metadata;namespace?Aop {class?Program{static?void?Main(string[]?args){Console.WriteLine("========原始需求=========");User?user?=?new?User?{?Name?=?"Zoe",?Age?=?18?};IUserService?userService?=?new?UserService();//?模擬增加一個用戶userService.AddUser(user);Console.WriteLine("========動態代理?實現新需求=========");//1.?創建代理對象IUserService?userService1?=?DispatchProxy.Create<IUserService,?MyProxy>();//2.?因為調用的是實例方法,需要傳提具體類型((MyProxy)userService1).TargetClass?=?new?UserService();userService1.AddUser(user);Console.WriteLine("=============Castle.Core方式==============");//先實例化一個代理類生成器ProxyGenerator?generator?=?new?ProxyGenerator();//通過代理類生成器創建var?u?=?generator.CreateInterfaceProxyWithTarget<IUserService>(new?UserService(),?new?MyIntercept());u.AddUser(user);Console.ReadLine();}} }運行效果如下:
Autofac集成了Castle.Core用著也挺不錯;
Autofac已經集成了Castle.Core啦,在聊MemoryCache的時候就已經用到,使用比較簡單,可以通過特性標注的方式就可以針對某個類或接口的方法進行攔截加強,詳情請參考這篇文章(因MemoryCache鬧了個笑話)。
3. 應用場景
AOP思想是很優秀,但總不能處處都得用吧,需根據業務來評估是否需要;常用應用場景大概有以下幾個:
安全控制:通常在Web開發的時候,會使用過濾器或攔截器進行權限驗證,這也是AOP思想的落地;對于客戶端程序,通過上述演示的幾種方式可以輕松實現權限的統一管理和驗證;
事務處理:相信小伙伴都寫過數據庫事務代碼吧,常規做法就是在業務方法中直接開啟事務,執行完成,提交或回滾即可,AOP思想也能很好處理這種情況;
異常處理:統一的異常處理是最好的選擇,除非是特殊的業務;通常Web有異常過濾器,客戶端程序可以用上述幾種方式;
日志記錄:目前來說日志記錄應該是作為系統功能的一部分,AOP統一記錄是不錯的選擇;
性能統計:以AOP的思想對方法進行前后監控,從而可以分析其執行性能;
緩存處理:緩存處理,如上次說到MemoryCache,加上AOP攔截應用,系統效率提升不錯哦
業務輔變主不變:主業務變,但會不定時增加輔助需求的場景,比如增加用戶,后續可能在用戶新增成功之后會增加郵件通知、推送新用戶信息等功能。
源碼地址:https://github.com/zyq025/DotNetCoreStudyDemo
總結
先暫時聊這么多吧,瞌睡啦,小伙伴們晚安嘍!!!
一個被程序搞丑的帥小伙,關注"Code綜藝圈",跟我一起學~~~
圖片總結
以上是生活随笔為你收集整理的AOP(面向切面编程)大概了解一下的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BeetleX使用bootstrap5开
- 下一篇: 如何选择 WebClient Http