一丶前言
看過一些描述關於AOP切面編程的文章,寫的太概念化讓人很難理解,下面是我本身的理解,但願能幫到新人,若有錯誤歡迎指正。html
二丶AOP是什麼,它的應用場景是什麼?
AOP也跟IOC,OOP這些思想同樣它只是一種編程思想。Autofac、Spring.Net、Castle這些組件實現了AOP切面編程思想的框架。AOP說白了就是在運行時,動態的將代碼切入到類的指定方法的指定位置上,這種思想就是面向切面的編程思想。git
若是你發現你的方法中有不少重複的代碼就能夠考慮用aop來精簡代碼了。好比說你想監控每一個方法的耗時,按照傳統的方法是每一個方法都加上監控代碼,若是用AOP思想去解決問題,就能夠把跟監控代碼放到方法的外面去寫。github
AOP思想的應用場景:web
AOP切面緩存編程
權限認證緩存
錯誤處理app
調試框架
日誌記錄async
性能監控性能
數據持久化
AOP事務
三丶AOP切面執行流程
AOP切面有點像攔截器,不過跟攔截器有點區別。
四丶代碼例子
這個例子開發環境使用的是.Net Core 3.0,用的AOP框架是Autofac,經過Nuget安裝Autofac.Extras.DynamicProxy組件。
使用步驟
1.Startup中把BlogCacheAOP切面 切入到Titan.Blog.AppService.dll下全部接口實現裏。
var servicesDllFile = Path.Combine(basePath, "Titan.Blog.AppService.dll");//獲取項目絕對路徑 var assemblysServices = Assembly.LoadFile(servicesDllFile); builder.RegisterAssemblyTypes(assemblysServices) .AsImplementedInterfaces() .InstancePerLifetimeScope() .EnableInterfaceInterceptors() .InterceptedBy(typeof(BlogCacheAOP));//AOP切面緩存
2.切面公共代碼
3.給方法標記特性,只有指定特性的方法纔會執行公共代碼
/// <summary> /// 獲取系統中全部的權限 /// </summary> /// <returns></returns> [Caching(AbsoluteExpiration = 10)] public async Task<List<SysRoleModuleButtonDto>> GeRoleModule() { var dto = await _iSysRoleModuleButtonRepository.QueryAsNoTracking(x => x.ModuleType == 0);// var roleModuleButton = dto.MapToList<SysRoleModuleButton, SysRoleModuleButtonDto>(); if (roleModuleButton.Count > 0) { foreach (var item in roleModuleButton) { item.SysRole = _iSysRoleRepository.QueryBySql($"select * from SysRole where SysRoleId='{item.SysRoleId}' and IsDelete!=1 and RoleStatus=1").Result.FirstOrDefault(); item.SysModule = _iSysModuleRepository.QueryBySql($"select * from SysModule where SysModuleId='{item.SysModuleId}' and ModuleStatus=1 and IsDelete!=1").Result.FirstOrDefault(); } } return roleModuleButton; }
這個是AOP切面緩存,它的功能是將包含CachingAttribute特性的方法的返回值緩存到Redis裏,下次在訪問這個方法,會先去緩存中查詢若是有則直接跳過這個方法,直接從Redis裏獲取以前緩存的結果集,若是沒有則會執行方法獲取返回值在緩存到Redis裏。
以此,咱們能夠開發其餘相似功能,好比性能監控,日誌監控,AOP事務,是否是很強大。具體代碼執行流程請下載這個項目(下面有github地址),本身調試下上面的例子就明白了。
*****還有一個要注意的,我這個項目控制器和服務實現解耦了,若是沒有解耦的話,控制器直接調服務的話,AOP註冊方式和服務要作修改。
1.Startup中AOP註冊代碼
////標記了虛方法virtual的纔會進入切面 var assemblysModels = Assembly.Load("Titan.Blog.AppService"); builder.RegisterAssemblyTypes(assemblysModels) .EnableClassInterceptors() .InterceptedBy(typeof(BlogCacheAOP));
2.方法要加上virtual,不然進不了切面
/// <summary> /// 獲取系統中全部的權限 /// </summary> /// <returns></returns> [Caching(AbsoluteExpiration = 10)] public virtual async Task<List<SysRoleModuleButtonDto>> GeRoleModule() { var dto = await _iSysRoleModuleButtonRepository.QueryAsNoTracking(x => x.ModuleType == 0);// var roleModuleButton = dto.MapToList<SysRoleModuleButton, SysRoleModuleButtonDto>(); if (roleModuleButton.Count > 0) { foreach (var item in roleModuleButton) { item.SysRole = _iSysRoleRepository.QueryBySql($"select * from SysRole where SysRoleId='{item.SysRoleId}' and IsDelete!=1 and RoleStatus=1").Result.FirstOrDefault(); item.SysModule = _iSysModuleRepository.QueryBySql($"select * from SysModule where SysModuleId='{item.SysModuleId}' and ModuleStatus=1 and IsDelete!=1").Result.FirstOrDefault(); } } return roleModuleButton; }
3.切面代碼不須要改動
四丶結語
AOP思想實際上就是想把業務和公共的處理分開,對原有的代碼沒有一點入侵。我以爲學習一個新技術以前,先別讀那麼多概念性的東西,感受越看越糊塗,只會對學習新技術產生恐懼和抵觸心理。咱們能夠先看看新技術它能解決什麼問題,應用場景是什麼,這對學習新技術應該是有好處的。
五丶Github Demo,演示地址