标签:权限控制 handle 完全 官方文档 repeat 解决 bytecode fun erro
AOP是所有现代OOP语言开发框架中都会具备的东西,随着Spring框架的普及,这个东西已经被玩烂了。可是很多人仍旧处于知其然不知其所以然的状态。本文将基于.NET环境探讨实现AOP的底层原理。
文中部分代码样例截图摘自Matthew D. Groves的《AOP in .NET》,推荐大家购买阅读。
中间件与过滤器原理截图摘自微软官方文档,请查看文中链接。
本文主要分为以下部分:
面向对象编程通过类的继承机制来复用代码,这在大多数情况下这很有用。但是随着软件系统的越来复杂,出现了一些通过OOP处理起来相当费力的关注点,比如:日志记录,权限控制,缓存,数据库事务提交等等。它们的处理逻辑分散于各个模块,各个函数之中,这违反了Don‘t Repeat Yourself以及关注度点分离原则,不利于后期的代码维护。所谓AOP(面向切面编程),就是将这些关注点,看作一个个切面,捕获这些切面并将其处理程序模块化的过程。
在.ASP.NET Core框架中,微软内置了一些处理AOP逻辑的机制。可惜的是它内置的IoC框架,不支持语言级别的AOP。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write
ASP.NET Core框架本身就是由一系列中间件组成的,它本身内置的异常处理,路由转发,权限控制,也就是在上述图中的请求管道中实现的。所以我们也完全可以基于中间件机制,实现AOP。
以异常处理为例,我可以将try catch加入到next方法的前后,以捕获后续运行过程中未处理的异常,并进行统一处理。代码如下:
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
public ExceptionHandlerMiddleware(RequestDelegate next )
{
_next = next;
}
public async Task Invoke(HttpContext context, IHostingEnvironment env,ILogger<ExceptionHandlerMiddleware> logger)
{
try
{
await _next(context);
}
catch (Exception ex)
{
logger.LogError(new EventId(ex.HResult), ex, ex.Message);
await context.HandleExceptionAsync(ex, env.IsDevelopment());
}
}
}
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters
过滤器本质上是由路由中间件(Routing Middleware)的请求管道实现的,如下图所示。
开发者通过定义并注册相应的过滤器,就能基于这个请求管道,来处理对应的关注点。Asp.NET Core 的过滤器执行顺序如下图:
我们可以基于中间件或者过滤器机制,完成简单的开发。可惜的是,这些并不是语言级别的aop。asp.net core是一个开发框架,它为了方便你开发,给你内置了一些条条框框,你照着做确实能够解决大部分问题。但是脱离了它,该如何实现AOP呢?
下面我们开始真正进入主题。
要实现AOP,关键在于织入(“weaving”)。如上图代码中,LogAspect被织入到BusinessModule1中,Mehtod1在执行前后,就会分别调用BeginMethod以及EndMethod方法来处理日志记录逻辑。LogAspect如果能够织入到所有需要日志记录的方法中,我们就将分散的日志处理代码模块化成了一个统一的切面处理程序:LogAspect。这就是AOP。实现织入的方式分为两种:编译时织入、运行时织入。
当你使用C#创建.NET项目时,该项目将被编译为CIL(也称为MSIL,IL和bytecode)作为程序集(DLL或EXE文件)。 下图说明了这个过程。然后,公共语言运行时(CLR)可以将CIL转换成真实的机器指令(通过称为即时编译的过程,或JIT)。
《aop in .net》
所谓编译时织入,就是对编译产生的CIL做手脚,通过修改编译好的CIL文件,来达到织入的效果,如下图所示。编译时织入可通过PostSharp实现。
运行时织入则是在程序运行时来完成的织入,一般是通过DynamicProxy(动态代理)程序(Castle.Core)配合IoC容器(Autofac,StructureMap等)来实现的。更多样例可查看:https://github.com/TylerBrinks/Snap
这两种织入模式各有利弊,下面总结几点:
你可以根据自己的需要选择合适的织入方式,不过由于PostSharp为商业付费项目,我后面不再对其进行过多讲解,需要的朋友可自行阅读《AOP in .NET》中的相关内容,或查阅PostSharp官网。
本文后面将主要通过代码样例讲述如何基于动态代理实现运行时织入。
(未完待续)
标签:权限控制 handle 完全 官方文档 repeat 解决 bytecode fun erro
原文地址:https://www.cnblogs.com/wswind/p/aop_in_dotnet.html