zoukankan      html  css  js  c++  java
  • Asp.Net Core轻量级Aop解决方案:AspectCore

    什么是AspectCore Project ?

    AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect-oriented programming) 解决方案,它更好的遵循Asp.Net Core的模块化开发理念,使用AspectCore可以更容易构建低耦合、易扩展的Web应用程序。AspectCore使用Emit实现高效的动态代理从而不依赖任何第三方Aop库。

    开使使用AspectCore

    • 启动 Visual Studio。从 File 菜单, 选择 New > Project。选择 ASP.NET Core Web Application 项目模版,创建新的 ASP.NET Core Web Application 项目。

    • 从 Nuget 安装 AspectCore.Extensions.DependencyInjection package:

      1 PM>   Install-Package AspectCore.Extensions.DependencyInjection
    • 在一般情况下可以使用抽象的AbstractInterceptorAttribute 自定义特性类,它实现IInterceptor接口。AspectCore默认实现了基于Attribute的拦截器配置。我们的自定义拦截器看起来像下面这样:
      public class CustomInterceptorAttribute : AbstractInterceptorAttribute
      {
          public async override Task Invoke(AspectContext context, AspectDelegate next)
          {
              try
              {
                  Console.WriteLine("Before service call");
                  await next(context);
              }
              catch (Exception)
              {
                  Console.WriteLine("Service threw an exception!");
                  throw;
              }
              finally
              {
                  Console.WriteLine("After service call");
              }
           }
       }
    • 定义ICustomService接口和它的实现类CustomService:
      public interface ICustomService
      {
          [CustomInterceptor]
          void Call();
      }
      public class CustomService : ICustomService
      {
          public void Call()
          {
              Console.WriteLine("service calling...");
          }
      }
    • HomeController中注入ICustomService:
      public class HomeController : Controller
      {
          private readonly ICustomService _service;
          public HomeController(ICustomService service)
          {
              _service = service;
          }
          public IActionResult Index()
          {
              _service.Call();
              return View();
          }
      }
    • 注册ICustomService,接着,在ConfigureServices中配置创建代理类型的容器:
      public IServiceProvider ConfigureServices(IServiceCollection services)
      {
          services.AddTransient<ICustomService, CustomService>();
          services.AddMvc();
          services.AddDynamicProxy();
          return services.BuildAspectCoreServiceProvider();
      }
    • 拦截器配置。

      全局拦截器。使用AddDynamicProxy(Action<IAspectConfiguration>)的重载方法,其中IAspectConfiguration提供Interceptors注册全局拦截器:

      services.AddDynamicProxy(config =>
       {
            config.Interceptors.AddTyped<CustomInterceptorAttribute>();
       });

      带构造器参数的全局拦截器,在CustomInterceptorAttribute中添加带参数的构造器:

      public class CustomInterceptorAttribute : AbstractInterceptorAttribute
      {
          private readonly string _name;
          public CustomInterceptorAttribute(string name)
          {
              _name = name;
          }
          public async override Task Invoke(AspectContext context, AspectDelegate next)
          {
              try
              {
                  Console.WriteLine("Before service call");
                  await next(context);
              }
              catch (Exception)
              {
                  Console.WriteLine("Service threw an exception!");
                  throw;
              }
              finally
              {
                  Console.WriteLine("After service call");
              }
          }
      }

      修改全局拦截器注册:

      services.AddDynamicProxy(config =>
      {
           config.Interceptors.AddTyped<CustomInterceptorAttribute>(args: new object[] { "custom" });
      });

      作为服务的全局拦截器。在ConfigureServices中添加:

      services.AddTransient<CustomInterceptorAttribute>(provider => new CustomInterceptorAttribute("service"));

      修改全局拦截器注册:

      services.AddDynamicProxy(config =>
      {
          config.Interceptors.AddServiced<CustomInterceptorAttribute>();
      });

      作用于特定ServiceMethod的全局拦截器,下面的代码演示了作用于带有Service后缀的类的全局拦截器:

      services.AddDynamicProxy(config =>
      {
          config.Interceptors.AddTyped<CustomInterceptorAttribute>(method => method.DeclaringType.Name.EndsWith("Service"));
      });

      使用通配符的特定全局拦截器:

      services.AddDynamicProxy(config =>
      {
          config.Interceptors.AddTyped<CustomInterceptorAttribute>(Predicates.ForService("*Service"));
      });
    • 在AspectCore中提供NonAspectAttribute来使得ServiceMethod不被代理:
      [NonAspect]
      public interface ICustomService
      {
          void Call();
      }

      同时支持全局忽略配置,亦支持通配符:

      services.AddDynamicProxy(config =>
        {
            //App1命名空间下的Service不会被代理
            config.NonAspectPredicates.AddNamespace("App1");
            //最后一级为App1的命名空间下的Service不会被代理
            config.NonAspectPredicates.AddNamespace("*.App1");
            //ICustomService接口不会被代理
            config.NonAspectPredicates.AddService("ICustomService");
            //后缀为Service的接口和类不会被代理
            config.NonAspectPredicates.AddService("*Service");
            //命名为Query的方法不会被代理
            config.NonAspectPredicates.AddMethod("Query");
            //后缀为Query的方法不会被代理
            config.NonAspectPredicates.AddMethod("*Query");
        });
    • 拦截器中的依赖注入。在拦截器中支持属性注入,构造器注入和服务定位器模式。
      属性注入,在拦截器中拥有public get and set权限的属性标记[AspectCore.Injector.FromContainerAttribute]特性,即可自动注入该属性,如:
      public class CustomInterceptorAttribute : AbstractInterceptorAttribute
      {
          [FromContainer]
          public ILogger<CustomInterceptorAttribute> Logger { get; set; }
          public override Task Invoke(AspectContext context, AspectDelegate next)
          {
              Logger.LogInformation("call interceptor");
              return next(context);
          }
      }

      构造器注入需要使拦截器作为Service,除全局拦截器外,仍可使用ServiceInterceptor使拦截器从DI中激活:

      public interface ICustomService
      {
          [ServiceInterceptor(typeof(CustomInterceptorAttribute))]
          void Call();
      }

      服务定位器模式。拦截器上下文AspectContext可以获取当前Scoped的ServiceProvider

      public class CustomInterceptorAttribute : AbstractInterceptorAttribute
      {
          public override Task Invoke(AspectContext context, AspectDelegate next)
          {
              var logger = context.ServiceProvider.GetService<ILogger<CustomInterceptorAttribute>>();
              logger.LogInformation("call interceptor");
              return next(context);
          }
      }

      AspectCore Project 项目地址: https://github.com/dotnetcore/AspectCore-Framework

  • 相关阅读:
    XML错误信息Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-4.0.xsd). For more information, right click on the message in the Problems View ...
    Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
    maven创建web报错Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins:maven-compiler-plugin:maven-compiler-plugin:3.5.1:runtime Cause: error in opening zip file
    AJAX跨域
    JavaWeb学习总结(转载)
    JDBC学习笔记
    Java动态代理之JDK实现和CGlib实现
    (转)看懂UML类图
    spring boot配置使用fastjson
    python3下django连接mysql数据库
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/13491726.html
Copyright © 2011-2022 走看看