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`
```csharp
using 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
实现在编译期间将原有功能改变,或在之前之后注入。