.netcore 中使用开源的AOP框架 AspectCore
程序员文章站
2023-08-29 17:54:08
AspectCore Project 介绍 什么是AspectCore Project ? AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect-oriented programming) 解决方案,它更好的遵循Asp.Net Core的模块化开 ......
aspectcore project 介绍
什么是aspectcore project ?
aspectcore project 是适用于asp.net core 平台的轻量级 aop(aspect-oriented programming) 解决方案,它更好的遵循asp.net core的模块化开发理念,使用aspectcore可以更容易构建低耦合、易扩展的web应用程序。
为什么要设计aspectcore ?
在传统.net framework和asp.net framework中,我们使用castle dynamicproxy 或者clr提供的 remoting.proxies 可以轻松的实现 aop 来分离关注点从而降低业务逻辑和基础框架功能的耦合。然而在asp.net core中,不仅缺乏细粒度的aop支持(middleware
和filter
都是asp.net core的内置aop实现,但仅适合在web层使用),castle也迟迟未能友好的支持asp.net core。
因此 aspectcore 提供了一个全新的轻量级和模块化的aop解决方案,下面是aspectcore的基本特性:
- 提供抽象的aop接口,基于该接口,可以轻松的使用自己的代理类实现替换默认的实现
- 框架不包含ioc,也不依赖具体的ioc实现,可以使用asp.net core的或任何兼容 asp.net core的第三方ioc来集成 aspectcore 到 asp.net core 应用程序中
- 高性能的异步拦截器系统
- 灵活的配置系统
- 基于
service
的而非基于实现类的切面构造 - 支持跨平台的asp.net core环境
上面是一些概念介绍,关于aop指的是面向切面编辑,其时我们之前用过,只是没注意而已,比如.netcore中的services中的方法,注入到服务中,权限过滤等都可以理解为aop.
下面使用aspectcore写一个注入的例子,可以应用到验证权限中。
- 首先创建一个.netcore api项目,使用nuget添加aspectcore.core、aspectcore.extensions.dependencyinjection包的引用,我两个用的是1.2.0版本
- 创建自定义属性类,继承自abstractinterceptorattribute
using aspectcore.dynamicproxy; using system; using system.collections.generic; using system.linq; using system.threading.tasks; namespace aspectcore { public class custominterceptorattribute: abstractinterceptorattribute { public async override task invoke(aspectcontext context, aspectdelegate next) { try { console.writeline("before service call"); await next(context); } catch (exception) { console.writeline("service threw an exception!"); throw; } finally { console.writeline("after service call"); } } } }
- 创建service类,添加属性过滤
using aspectcore.dynamicproxy; using system; using system.collections.generic; using system.linq; using system.threading.tasks; namespace aspectcore.services { public interface icustomservice { [custominterceptor] void call(); } public class customservice : icustomservice { public void call() { console.writeline("service calling..."); } } }
- 创建home控制器,添加测试action
using system; using system.collections.generic; using system.linq; using system.threading.tasks; using aspectcore.services; using microsoft.aspnetcore.http; using microsoft.aspnetcore.mvc; namespace aspectcore.controllers { [route("api/[controller]")] [apicontroller] public class homecontroller : controllerbase { private readonly icustomservice _service; public homecontroller(icustomservice service) { _service = service; } [httpget("getmsg")] public void getmsg() { _service.call(); } } }
- 在startup中注入服务,主要是configureservices中做了修改
using system; using aspectcore.configuration; using aspectcore.extensions.dependencyinjection; using aspectcore.injector; using aspectcore.services; using microsoft.aspnetcore.builder; using microsoft.aspnetcore.hosting; using microsoft.aspnetcore.mvc; using microsoft.extensions.configuration; using microsoft.extensions.dependencyinjection; namespace aspectcore { public class startup { public startup(iconfiguration configuration) { configuration = configuration; } public iconfiguration configuration { get; } // this method gets called by the runtime. use this method to add services to the container. public iserviceprovider configureservices(iservicecollection services) { //根据属性注入来配置全局拦截器 services.configuredynamicproxy(config => { config.interceptors.addtyped<custominterceptorattribute>();//custominterceptorattribute这个是需要全局拦截的拦截器 }); services.addmvc().setcompatibilityversion(compatibilityversion.version_2_1); ; services.addsingleton<icustomservice, customservice>(); var servicecontainer = services.toservicecontainer();//容器 return servicecontainer.build(); } public void configure(iapplicationbuilder app, ihostingenvironment env) { if (env.isdevelopment()) { app.usedeveloperexceptionpage(); } else { app.usehsts(); } app.usehttpsredirection(); app.usemvc(); } } }
- 最后运行项目,即可查看运行结果,网上有的说只能调用control中action方法为virtual方法才能成功,其实是错误的。
- 目录结构如下