Loading

如何自定义中间件,实现业务代码无侵入监控及拦截

 

 定义


  先看看某度某科怎么定义的 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

 

  通俗的说就是,在进入你的业务逻辑代码之前,先执行一些方法操作,或者业务方法执行之后,继续执行一些操作方法,可以用来做什么呢 
 

  • 你想给你的网站加上鉴权,
  • 对某些url,你认为不需要鉴权就可以访问,
  • 对于某些url,你认为需要有特定权限的用户才能访问
  • 对于某些业务方法,我想监控调用频率,执行性能
  • 还有骚操作的一种。收集用户经常访问的模块,搜索关键字,喜欢看什么,使用习惯,(看到这里,笑容渐渐邪恶啊)提供模型给我们的算法和机器学习,用来优化我们的推荐机制,没错,就是你在一个网页里搜索了东西,其他的app或者网页,会推送相关的广告给你(诶,有意思了啊)  

      

 

 总结


 

 个人理解其实AOP像OOP一样,只是一种编程范式,AOP并没有规定说,实现AOP协议的代码,要用什么方式去实现,只要达到对业务代码无侵入,就可以说是AOP
 
 
 
Demo

 

  闲言少叙,代码见,先安装nuget包
  Castle.Core 、 Autofac 、 Autofac.Extras.DynamicProxy
 
  这里先默认各位同学都会用autofac,不会也没关系,这个是完整的代码链接 
  
  先定义最核心的中间件ServiceAOP类,继承 IInterceptor 接口  , 有两种方式实现aop拦截
      
  public class ServiceAOP: IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            DoSomething();
             Console.WriteLine("我要收集请求参数,发给我们算法模型同学 \"{0}\"  参数是 {1}... ", invocation.Method.Name,   string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));
            //执行真实业务方法
            invocation.Proceed();
        }

        public void DoSomething()
        {
            Console.WriteLine("AOP,我先说话,你们service稍后再发言!");
        }
    }

 

 

第一种

  注册自定义的aop拦截中间件

 builder.RegisterType<ServiceAOP>().As<IInterceptor>().InstancePerDependency();
  注册业务接口方法的同时 注入aop拦截中间件
 //第一种方式
builder.RegisterType<TestServiceTwo>().As<ITestServiceTwo>().InterceptedBy(typeof(IInterceptor)) .InstancePerDependency().EnableClassInterceptors();

 

 

第二种

 
  还是先注册自定义的aop拦截中间件
  
builder.Register(c => new ServiceAOP())

 

  再在需要拦截的程序集上注入aop拦截中间件,
var serviceAsm = Assembly.Load(new AssemblyName("Sharper.Core"));
            builder.RegisterAssemblyTypes(serviceAsm)
                       .Where(t => typeof(ITagService).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract)
                       .AsImplementedInterfaces()
                       .InstancePerLifetimeScope()
                       .EnableInterfaceInterceptors(); //注入拦截器

 

  注册程序集下所有继承ITagService的接口,并注入拦截中间件

  最后在需要拦截的实现类上,直接通过打标签的形式,即可实现拦截效果

[Intercept(typeof(ServiceAOP))]
    public class TestServiceOne : ITestServiceTwo
    {
        public async Task FirstMethod()
        {
            //doSomething 业务逻辑
            await Task.Run(() =>
            {
                Console.WriteLine($"业务方法:TestServiceTwo.FirstMethod()执行成功...");
            });
        }
    }

 

 

  这样,在执行ITestServiceTwo 接口的业务方法之前,都会先执行aop中间件的方法操作

 


 
  有些同学想问,你这是业务接口方法,我们想拦击ApiController控制器的请求,怎么处理呀,别急,这就来
 
  .net core web项目,可以对ApiController 控制器和业务方法 分别进行拦截,互不影响

  public class RequestCultureMiddleware
    {
        //定义私有只读的委托 RequestDelegate
        private readonly RequestDelegate _next;

        public RequestCultureMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        //定义名为Invoke 或 InvokeAsync 的方法,参数为HttpContext 
        public async Task InvokeAsync(HttpContext context)
        {
            Console.WriteLine($"api 请求进来了,action{context.Request.Path}");
            // Call the next delegate/middleware in the pipeline
            await _next(context);
        }
    }
这个是微软提供的,专门用于拦截http请求的中间件的组件,正好用于控制器拦截
在 Startup 的Configure 方法注入 使用中间件 app.UseMiddleware<RequestCultureMiddleware>();

 

这个就是本文好说的内容,其实aop中间件的玩法有很多,不止于上面说的哪几种,好可以,实现缓存拦截,不同的业务方法 分别进行不同数据库初始化,同学们可以探索一下新玩法,个人感觉,这个对项目的完整性和效率帮助还是挺大的。

 

 

 

欢迎各位转载,转载文章必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

 

 
 

 

 

posted @ 2020-09-23 12:05  打滚的姚先森  阅读(1007)  评论(0编辑  收藏  举报