1.什么是AOP
AOP是Aspect Oriented Programming的缩写,意为面向切面编程。是指在编译的时候或者运行期间实现一些功能。将代码切入到类的指定位置上,大部分是方法之前或之后。
2.为什么使用AOP
- 解决重复编码,比如打印日志,记录接口执行时间
- 针对业务无关的逻辑处理,比如授权。将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。
- 在不改变原有代码的基础上,从外部切入,实现功能的扩展。
- 将思维解放,从而在不同的视角解决问题。
3.实现
3.1 过滤器Filter
作为.NET Core的使用人员,你肯定或多或少的接触过Filter来实现一些功能。比如[IActionFilter](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.filters.iactionfilter)、[IExceptionFilter](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.filters.iexceptionfilter)。
新建ASP.NET Core空项目AopDemo
新建类LoggerFilter继承IActionFilter并实现。 ```csharp using Microsoft.AspNetCore.Mvc.Filters;
namespace AopDemo { public class LoggerFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { System.Console.WriteLine(“这是开始”); }
public void OnActionExecuted(ActionExecutedContext context){System.Console.WriteLine("这是结束");}}
}
新建`HomeController````csharpusing Microsoft.AspNetCore.Mvc;using System.Threading.Tasks;namespace AopDemo{[Route("[controller]/[action]")]public class HomeController : ControllerBase{[HttpGet]public Task Go(){System.Console.WriteLine("Go");return Task.CompletedTask;}}}
修改Startup
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace AopDemo{public class Startup{public void ConfigureServices(IServiceCollection services){services.AddControllers(options => options.Filters.Add<LoggerFilter>());}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}}}
在浏览器中输入http://localhost:5000/home/go
3.2 中间件Middleware
使用中间件,也是一种AOP思想的应用。
继续使用上面的项目,新建类LoggerMiddleware继承IMiddleware
using Microsoft.AspNetCore.Http;using System;using System.Diagnostics;using System.Threading.Tasks;namespace AopDemo{public class LoggerMiddleware : IMiddleware{public async Task InvokeAsync(HttpContext context, RequestDelegate next){Stopwatch sw = Stopwatch.StartNew();await next(context);sw.Stop();Console.WriteLine("执行:{0},耗时:{1}", context.Request.Path, sw.Elapsed);}}}
Startup类注入LoggerMiddleware,并使用中间件app.UseMiddleware<LoggerMiddleware>()
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace AopDemo{public class Startup{public void ConfigureServices(IServiceCollection services){services.AddControllers(options => options.Filters.Add<LoggerFilter>());services.AddTransient<LoggerMiddleware>();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseMiddleware<LoggerMiddleware>();app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}}}
在浏览器中输入http://localhost:5000/home/go
3.3 动态代理 Dynamic Proxy
Castle
TODO
以上都是在运行期间进行实现功能,也可以使用Fody实现在编译期间将原有功能改变,或在之前之后注入。
