在.NET Core中三种实现“可插拔”AOP编程方式(附源码)

简介: 一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点。 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),DynamicProxy(动态代理方式,JAVA上早已不是新鲜事),Middleware(netcore中间件所实现的AOP方式)   什么是AOP编程 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

一看标题肯定会联想到使用动态编织的方式实现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

相关文章
|
2月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
57 1
|
26天前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
2天前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
13 5
|
10天前
|
传感器 数据采集 物联网
探索.NET nanoFramework:为嵌入式设备编程的新途径
探索.NET nanoFramework:为嵌入式设备编程的新途
24 7
|
2月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
75 3
|
16天前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
20天前
|
Java 容器
AOP面向切面编程
AOP面向切面编程
37 0
|
2月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
44 13
|
2月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。