ASP.NETCore 切面編程AOP 詳解


一.AOP概述:

  AOP(Aspect Oriented Programming),即面向切面編程。采用“橫切”的思想,將軟件系統的系統功能業務功能分開。

  系統功能主要有

    1.緩存模塊:用於緩存數據,與系統業務功能關系不大,用於提升系統性能。當數據請求過來時,是否要從緩存讀取,當緩存沒有數據時,

       是否要將獲取到的數據放入緩存,以便下次數據請求時從緩存讀取。比較常用的緩存工具有monogodb,redis。

    2.驗證模塊:判斷當前用戶是否有獲取該條數據 或者執行 該操作的權限。

    3.日志模塊:收集當前用戶的操作痕跡,或者記錄系統出現的問題,后期可進行大數據行為分析。

       業務功能:系統處理用戶請求的正常邏輯功能。

       http請求過來后,會先經過系統功能的橫切攔截,才會到業務功能處理請求。AOP具體過程如下圖所示:

         

二、AOP實現:

  國內大佬基於.NETStand 實現了一個AOP的框架,其源碼地址為  https://github.com/dotnetcore/AspectCore-Framework

  要使用該框架,可通過Nuget 將 AspectCore.Extensions.DependencyInjection 引用到項目中,可實現日志攔截和緩存攔截,該框架是基於IOC容器的。

     這里,我用控制台程序來演示:首先,先nuget 引用 AspectCore.Extensions.DependencyInjection。

  1.程序入口:     

class Program
    {
        static void Main(string[] args)
        {
            //創建用於注冊服務的IOC容器 ServiceCollection
            ServiceCollection services = new ServiceCollection();

            //在容器中 注冊服務
            services.ConfigureDynamicProxy();
            services.AddScoped<IMySql, MySql>();

            //創建ServiceProvider,用於獲取服務。
            var provider = services.BuildDynamicProxyProvider();

            //獲取服務。
            var mysql = provider.GetService<IMySql>();
            
            //執行服務。
            var msg=mysql.GetById(10);

            //第一次去數據,從業務邏輯取數據
            var value = mysql.GetData("hehe");
            Console.WriteLine(value);

            //第二次去數據,從緩存取
            value = mysql.GetData("hehe");
            Console.WriteLine(value);

            Console.ReadKey();
            Console.WriteLine("Hello World!");
        }
    }

 

  2.系統功能 切面部分(AOP):

     日志切面:

    /// <summary>
    /// 日志模塊:(日志切面,日志AOP)
    /// </summary>
    public class MyLogInterceptorAttribute : AbstractInterceptorAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context">委托的參數,這里傳遞的是 GetById 方法</param>
        /// <param name="next">委托,委托的動作要看具體傳進來的方法的動作是什么</param>
        /// <returns></returns>
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            Console.WriteLine("開始記錄日志.......");

            //var aa = context;
            //var bb = next;
            var task = next(context);//從這里開始執行具體的方法。這里執行的是 GetById;
            Console.WriteLine("結束記錄日志.......");
            return task;
        }
    }

   緩存切面:

public class MyCacheInterceptorAttribute : AbstractInterceptorAttribute
    {
        //用於模擬緩存
        private Dictionary<string, string> CacheDic = new Dictionary<string, string>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context">委托的參數,這里傳遞的是 GetById 方法</param>
        /// <param name="next">委托,委托的動作,要看具體傳進來的方法的動作是什么</param>
        /// <returns></returns>
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            //獲取 傳遞過來的AspectContext,即傳進來的方法 的參數。
            var cacheKey = string.Join(",", context.Parameters);

            //從緩存去數據。如果緩存有,則返回
            if (CacheDic.ContainsKey(cacheKey))
            {
                context.ReturnValue = CacheDic[cacheKey].ToString();
                return Task.CompletedTask;
            }

            //緩存沒有,從業務邏輯取數據,去到數據后,將數據放入緩存
            var task = next(context);
            var cacheValue = context.ReturnValue.ToString();
            CacheDic.Add(cacheKey, "From cache:"+cacheValue);

            return task;
        }
    }

  

  3.業務功能部分:

    public interface IMySql
    {
        string GetById(int id);
        string GetData(string key);
    }

    public class MySql : IMySql
    {
        [MyLogInterceptor] //日志切面
        public string GetById(int id)
        {
            var msg = $"已經獲取到ID為{id}的數據";
            Console.WriteLine(id);
            return msg;
        }

        [MyCacheInterceptor] //緩存切面
        public string GetData(string key)
        {
            return "獲取數據";
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM