在.NET Core中三种实现“可插拔”AOP编程方式(附源码)
一看标题肯定会联想到使用动态编织的方式实现aop编程,不过这不是作者本文讨论的重点。
本文讨论另外三种在netcore中可实现的方式,filter(过滤器,严格意义上它算是aop方式),dynamicproxy(动态代理方式,java上早已不是新鲜事),middleware(netcore中间件所实现的aop方式)
什么是aop编程
在软件业,aop为aspect oriented programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。aop是oop的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
换白话文就是:保证开闭原则的前提下,不修改某一个模块(或函数)的任何一行代码,从而实现对该模块的横向扩展。
可插拔:即使抛弃aop,核心内容仍然可以运行,降低耦合,提高可重用。
创建一个“能说你好,某某某”的asp .net core webapi项目
创建项目步骤此处略过,呵呵。
我们假定一个最简单的“say hello”作为项目需求,通过url传递姓名,再返回“hello {name}”。因此创建一个简单模型peoplemodel,创建一个接口isay,并用say实现isay中的“hello {name}”功能。
1 public interface isay 2 { 3 peoplemodel sayhello(peoplemodel peoplemodel); 4 }
1 public class say : isay 2 { 3 public peoplemodel sayhello(peoplemodel peoplemodel) 4 { 5 peoplemodel.name = $"hello {peoplemodel.name}"; 6 return peoplemodel; 7 } 8 }
1 public class peoplemodel 2 { 3 public string name { get; set; } = ""; 4 public int age { get; set; } 5 public int sex { get; set; } 6 }
再创建一个mvc控制器
1 [route("api/[controller]")] 2 [apicontroller] 3 public class democontroller : controllerbase 4 { 5 [httpget] 6 public peoplemodel get([fromquery] peoplemodel peoplemodel) 7 { 8 return say.sayhello(peoplemodel); 9 } 10 }
很简单的,不做解释,以免浪费篇幅。
dynamicproxy方式
动态代理的方式在java上很早就出现了,比如在spring框架里面。而net中利用autofac和castle这两个框架同样也可以实现动态代理。
需要用到的框架如下:
autofac:提供容器控制
autofac.extensions.dependencyinjection:对autofac依赖注入进行扩展
autofac.extras.dynamicproxy:对autofac动态代理进行扩展
castle.core:使用动态代理的实现
相信autofac很多朋友都不陌生了,而配合castle框架就能实现动态代理模式,我们新建一个拦截器类,名为injectinterceptor,而且必须要实现iinterceptor(该接口在castle.dynamicproxy中),完整代码如下:
1 using system; 2 using castle.dynamicproxy; 3 4 namespace interceptdemo.intercepts.inject 5 { 6 public class injectinterceptor : iinterceptor 7 { 8 public virtual void intercept(iinvocation invocation) 9 { 10 preproceed(invocation); 11 invocation.proceed(); 12 postproceed(invocation); 13 } 14 15 private void preproceed(iinvocation invocation) 16 { 17 console.writeline($"{datetime.now} inject interceptor invoke preproceed"); 18 } 19 20 private void postproceed(iinvocation invocation) 21 { 22 console.writeline($"{datetime.now} inject interceptor invoke postproceed"); 23 } 24 } 25 }
当继承iinterceptor接口时,必须要实现intercept虚方法,该方法将传递iinvocation接口参数,调用proceed函数将会实现方法体以外的函数,就是切面以外的函数。使用时只需要通过特性即可实现aop方式,我们稍微修改一下say这个类,增加一句话:[intercept(typeof(injectinterceptor))]
当然,还需要在autofac中实现注册才行,代码如下:
var builder = new containerbuilder(); builder.populate(services); builder.registertype<say>().as<isay>().enableinterfaceinterceptors(); builder.registertype<injectinterceptor>();
filter方式
过滤器的方式就更加简单了,在asp.net框架中,使用过滤器的地方非常非常的多,笔者不作一一介绍,直接贴代码:
1 public class actionfilter : actionfilterattribute 2 { 3 public override void onactionexecuting(actionexecutingcontext context) 4 { 5 console.writeline($"{datetime.now} on action exceuting"); 6 } 7 8 public override void onactionexecuted(actionexecutedcontext context) 9 { 10 console.writeline($"{datetime.now} on action exceuted"); 11 } 12 }
middleware方式
中间件不仅可以实现自定义管道,还也可以作为netcore invoke的aop编程。我们先建立一个对applicationbuilder的扩展类
1 public static class intercepthandler 2 { 3 public static iapplicationbuilder useinterceptmiddleware(this iapplicationbuilder app) 4 { 5 return app.usemiddleware<interceptmiddlware>(); 6 } 7 }
再建立一个中间件
1 using system; 2 using system.threading.tasks; 3 using microsoft.aspnetcore.http; 4 5 namespace interceptdemo.intercepts.middleware 6 { 7 public class interceptmiddlware 8 { 9 private readonly requestdelegate _next; 10 11 public interceptmiddlware(requestdelegate next) 12 { 13 _next = next; 14 } 15 16 public async task invoke(httpcontext context) 17 { 18 preproceed(context); 19 await _next(context); 20 postproceed(context); 21 } 22 23 private void preproceed(httpcontext context) 24 { 25 console.writeline($"{datetime.now} middleware invoke preproceed"); 26 } 27 28 private void postproceed(httpcontext context) 29 { 30 console.writeline($"{datetime.now} middleware invoke postproceed"); 31 } 32 } 33 }
运行结果如下
总结一下
在netcore中可以使用aop的方式有很多很多,包括国内优秀的开源框架asp.netcore同样可以实现aop编程模式。
笔者所提供的三种aop方式可适用如下
filter:身份验证,参数验证,处理耗时等等web处理级的服务。
dynamicproxy:功能模块之间的解耦和重用服务。
middleware:request和response之间建立的通信等底层服务,必要时还可以实现自定义管道。
感谢阅读!
源码地址:https://github.com/steveleecn87/c-.three.aop.programming