在.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}”功能。
public interface ISay
{
PeopleModel SayHello(PeopleModel peopleModel);
}
public class Say : ISay
{
public PeopleModel SayHello(PeopleModel peopleModel)
{
peopleModel.Name = $"hello {peopleModel.Name}";
return peopleModel;
}
}
public class PeopleModel
{
public string Name { get; set; } = "";
public int Age { get; set; }
public int Sex { get; set; }
}
再创建一个MVC控制器
[Route("api/[controller]")]
[ApiController]
public class DemoController : ControllerBase
{
[HttpGet]
public PeopleModel Get([FromQuery] PeopleModel peopleModel)
{
return Say.SayHello(peopleModel);
}
}
很简单的,不做解释,以免浪费篇幅。
DynamicProxy方式
动态代理的方式在JAVA上很早就出现了,比如在Spring框架里面。而NET中利用Autofac和Castle这两个框架同样也可以实现动态代理。
需要用到的框架如下:
Autofac:提供容器控制
Autofac.Extensions.DependencyInjection:对autofac依赖注入进行扩展
Autofac.Extras.DynamicProxy:对autofac动态代理进行扩展
Castle.Core:使用动态代理的实现
相信autofac很多朋友都不陌生了,而配合Castle框架就能实现动态代理模式,我们新建一个拦截器类,名为InjectInterceptor,而且必须要实现IInterceptor(该接口在Castle.DynamicProxy中),完整代码如下:
using System;
using Castle.DynamicProxy; namespace InterceptDemo.Intercepts.Inject
{
public class InjectInterceptor : IInterceptor
{
public virtual void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed();
PostProceed(invocation);
} private void PreProceed(IInvocation invocation)
{
Console.WriteLine($"{DateTime.Now} inject interceptor invoke preproceed");
} private void PostProceed(IInvocation invocation)
{
Console.WriteLine($"{DateTime.Now} inject interceptor invoke postproceed");
}
}
}
当继承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框架中,使用过滤器的地方非常非常的多,笔者不作一一介绍,直接贴代码:
public class ActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine($"{DateTime.Now} on action exceuting");
} public override void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine($"{DateTime.Now} on action exceuted");
}
}
Middleware方式
中间件不仅可以实现自定义管道,还也可以作为netcore invoke的AOP编程。我们先建立一个对ApplicationBuilder的扩展类
public static class InterceptHandler
{
public static IApplicationBuilder UseInterceptMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<InterceptMiddlware>();
}
}
再建立一个中间件
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; namespace InterceptDemo.Intercepts.Middleware
{
public class InterceptMiddlware
{
private readonly RequestDelegate _next; public InterceptMiddlware(RequestDelegate next)
{
_next = next;
} public async Task Invoke(HttpContext context)
{
PreProceed(context);
await _next(context);
PostProceed(context);
} private void PreProceed(HttpContext context)
{
Console.WriteLine($"{DateTime.Now} middleware invoke preproceed");
} private void PostProceed(HttpContext context)
{
Console.WriteLine($"{DateTime.Now} middleware invoke postproceed");
}
}
}
运行结果如下
总结一下
在NETCORE中可以使用AOP的方式有很多很多,包括国内优秀的开源框架asp.netcore同样可以实现AOP编程模式。
笔者所提供的三种AOP方式可适用如下
Filter:身份验证,参数验证,处理耗时等等WEB处理级的服务。
DynamicProxy:功能模块之间的解耦和重用服务。
Middleware:Request和Response之间建立的通信等底层服务,必要时还可以实现自定义管道。
感谢阅读!
源码地址:https://github.com/steveleeCN87/C-.three.aop.programming
在.NET Core中三种实现“可插拔”AOP编程方式(附源码)的更多相关文章
- 微信小程序中如何实现分页下拉加载?(附源码)
转眼间坚持写教你微信小程序系列已经有十节系列课程了,每天的工作压力繁重,小女子也不知道自己还能坚持这样的系列教程多久.只希望每篇教程真的对大家有帮助.这节课我们要介绍的就是如何实现分页的下拉加载,我们 ...
- .NET Core 中三种模式依赖注入的生命周期。
注入模式 同一个请求作用域 不同的请求作用域 AddSingleton 同一个实例 同一个实例 AddScoped 同一个实例 新实例 AddTransient 新实例 新实例
- EF Core 快速上手——EF Core的三种主要关系类型
系列文章 EF Core 快速上手--EF Core 入门 本节导航 三种数据库关系类型建模 Migration方式创建和习修改数据库 定义和创建应用DbContext 将复杂查询拆分为子查询 本 ...
- iOS开发UI篇—iOS开发中三种简单的动画设置
iOS开发UI篇—iOS开发中三种简单的动画设置 [在ios开发中,动画是廉价的] 一.首尾式动画 代码示例: // beginAnimations表示此后的代码要“参与到”动画中 [UIView b ...
- C#中三种定时器对象的比较
·关于C#中timer类 在C#里关于定时器类就有3个1.定义在System.Windows.Forms里2.定义在System.Threading.Timer类里3.定义在System.Timers ...
- 转-Web Service中三种发送接受协议SOAP、http get、http post
原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...
- C#中三种定时器对象的比较 【转】
https://www.cnblogs.com/zxtceq/p/5667281.html C#中三种定时器对象的比较 ·关于C#中timer类 在C#里关于定时器类就有3个1.定义在System.W ...
- Spring中三种配置Bean的方式
Spring中三种配置Bean的方式分别是: 基于XML的配置方式 基于注解的配置方式 基于Java类的配置方式 一.基于XML的配置 这个很简单,所以如何使用就略掉. 二.基于注解的配置 Sprin ...
- 深入浅出spring IOC中三种依赖注入方式
深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...
随机推荐
- 分布式计算课程补充笔记 part 2
▶ 并行计算八字原则:负载均衡,通信极小 ▶ 并行计算基本形式:主从并行.流水线并行.工作池并行.功能分解.区域分解.递归分治 ▶ MPI 主要理念:进程 (process):无共享存储:显式消息传递 ...
- Maven CXF wsdl2Java 给指定名空间设置包名
<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin< ...
- Rabbitmq(4) 订阅模式
p;发送者 x: 交换机 消息队列 c: 接收者 ------------------------------------------------------------------------ 发送 ...
- GIT BRANCHING
GIT BRANCHING generalizations Let's take a moment to review the main concepts and commands from the ...
- 关于HashMap和HashTable.md
目录 先来些简单的问题 你用过HashMap吗?" "什么是HashMap?你为什么用到它?" "你知道HashMap的工作原理吗?" "你 ...
- 接口自动化测试链接https://www.cnblogs.com/finer/
https://www.cnblogs.com/finer/ 测试框架的基本原则:业务逻辑与测试脚本分离,测试脚本与测试数据分离: 接口自动化的两种方式:工具(jmeter).代码(使用的是pytho ...
- 吴裕雄 python深度学习与实践(13)
import numpy as np import matplotlib.pyplot as plt x_data = np.random.randn(10) print(x_data) y_data ...
- tab页
图片: 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...
- Solidity的三种合约间的调用方式 call、delegatecall 和 callcode
0x00 前言 Solidity(http://solidity.readthedocs.io/en/v0.4.24/) 是一种用与编写以太坊智能合约的高级语言,语法类似于 JavaScript. S ...
- grafana add custom dashboard
grafana-dashboard-json prometheus-operator helm 中的grafana dashboard 扩展的时候,需要转换下载(https://grafana.com ...