zoukankan      html  css  js  c++  java
  • 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 "获取数据";
            }
        }
  • 相关阅读:
    为什么基于TCP的应用需要心跳包(TCP keep-alive原理分析)
    「DDoS攻击」兴风作浪,教你如何有效防护!
    你还敢乱粘贴吗?
    TODO git如何去掉烦人的merge?
    Git修改已经push到远程的commit信息
    Oracle删除唯一索引失败提示ORA-01418:指定的索引不存在 ORACLE
    mybatis逆向生成代码 [ERROR] No plugin found for prefix 'mybatis-generator' in the current project and in the plugin groups
    MySQL 中 redo log、undo log、binlog 的总结
    VATT: Transformers for Multimodal Self-Supervised Learning from Raw Video, Audio and Text
    OPT: Omni-Perception Pre-Trainer for Cross-Modal Understanding and Generation
  • 原文地址:https://www.cnblogs.com/Fengyinyong/p/13664311.html
Copyright © 2011-2022 走看看