Asp.net Core 3.1基于AspectCore实现AOP实现事务、缓存拦

编程学习 2021-07-04 22:42www.dzhlxh.cn编程入门
这篇文章主要介绍了Asp.net Core 3.1基于AspectCore实现AOP实现事务、缓存拦截器功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

最近想给我的框架加一种功能,就是比如给一个方法加一个事务的特性Attribute,那这个方法就会启用事务处理。给一个方法加一个缓存特性,那这个方法就会进行缓存。

这个也是网上说的面向切面编程AOP。

AOP的概念也很好理解,跟中间件差不多,说白了,就是我可以任意地在方法的前面或后面添加代码,这很适合用于缓存、日志等处理。

在net core2.2时,我当时就尝试过用autofac实现aop,但这次我不想用autofac,我用了一个更轻量级的框架,AspectCore。

用起来非常非常的简单,但一开始还是走了一点弯路,主要是网上都是net core3以下的教程,3以下的使用方法跟之前有一些不同。

先安装NuGet包,包名:AspectCore.Extensions.DependencyInjection

然后在Program.cs类中增加一行代码,这是net core 3的不同之处,这句添加的代码,意思就是用AspectCore的IOC容器替换内置的。因为AOP需要依靠IOC实现,所以必须得替换掉内置的IOC。

public class Program
  {
    public static void Main(string[] args)
    {
      CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
        webBuilder.UseStartup<Startup>();
      })
      //用AspectCore替换默认的IOC容器
      .UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
}

然后在Startup.cs类中的ConfigureServices中添加代码。(其实这个加不加都可以,如果需要配置就加,例如全局的拦截器、只拦截哪些匹配的服务,因为我只用特性进行拦截,所以我就什么也没配置)

services.ConfigureDynamicProxy(o=> { 
   //添加AOP的配置
});

这样AOP就配置好了,是不是很简单。

当然使用方面也需要注意一下,可以在接口、接口的方法、类,类的virtual方法上进行拦截。还有如果你想拦截控制器的action的话,那需要在ConfigureService里AddControllerAsServices

services.AddControllers()
//把控制器当成服务
.AddControllersAsServices()

狼蚁网站SEO优化我列出我的事务拦截器代码,如果是特性拦截,就继承AbstractInterceptorAttribute,如果要写一个全局拦截器,就AbstractInterceptor,然后在ConfigureDynamicProxy中进行配置,这个我就不介绍了

如果你的拦截器是放在其他项目的,那要记得添加AspectCore.Core包,不要只添加AspectCore.Abstractions,我一开始就只添加了AspectCore.Abstractions,一直没发现IsAsync、UnwrapAsyncReturnValue等一些扩展方法。

public class TransactionInterceptorAttribute : AbstractInterceptorAttribute
  {
    public async override Task Invoke(AspectContext context, AspectDelegate next)
    {
      var dbContext = context.ServiceProvider.GetService<AppDbContext>();
      //先判断是否已经启用了事务
      if (dbContext.Database.CurrentTransaction == null)
      {
        await dbContext.Database.BeginTransactionAsync();
        try
        {
          await next(context);
          dbContext.Database.CommitTransaction();
        }
        catch (Exception ex)
        {
          dbContext.Database.RollbackTransaction();
          throw ex;
        }
      }
      else
      {
        await next(context);
      }
    }
  }

然后我就可以这么优雅地使用事务了

我再列出我的缓存拦截器,(感谢网友的提醒,我做了一下修改,针对异步方法返回值的处理),对了,狼蚁网站SEO优化的ICacheHelper是我定义的一个缓存助手接口,用的是redis,我会在后面写一篇博客

public class CacheInterceptorAttribute : AbstractInterceptorAttribute
  {
    /// <summary>
    /// 缓存秒数
    /// </summary>
    public int ExpireSeconds { get; set; }

    public async override Task Invoke(AspectContext context, AspectDelegate next)
    {
      //判断是否是异步方法
      bool isAsync = context.IsAsync();
      //if (context.ImplementationMethod.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null)
      //{
      //  isAsync = true;
      / 

Copyright © 2016-2025 www.dzhlxh.cn 金源码 版权所有 Power by

网站模板下载|网络推广|微博营销|seo优化|视频营销|网络营销|微信营销|网站建设|织梦模板|小程序模板