• 使用AspectCore动态代理


    前言

    最近越来越多的同学关注到AspectCore,并且提出不少中肯的建议,其中最多的提议是希望能够看到更多的关于AspectCore使用方式的文章和Demo。那么在这篇文章里,我们就来聊聊AspectCore核心之一的动态代理。

    动态代理

    在.NET平台中,静态织入和动态代理是实现AOP的两种方式。其中静态织入在编译时通过在MSBiuld执行自定义的Build Task来拦截编译过程,在生成的程序集里插入自己的IL。而动态代理则是在运行时通过Emit技术生成动态程序集和动态代理类型从而对目标方法进行拦截。不管那种方式,都需要对MSIL有足够的理解,如果读者想要学习MSIL相关的技术,我在这里推荐《NET探秘MSIL权威指南》一书。
    AspectCore使用了动态代理作为AOP的实现,而不使用理论上性能更优的静态织入实现,是由于个人觉得动态代理方式可以做到更好的IoC进行集成并且能够在切面中获取更多的运行时元数据信息,并且在经过不断优化后,AspectCore动态代理的性能已经不落后静态织入的实现方式。

    如何使用

    在之前的文章里,只是简单的介绍了AspectCore,导致了很多同学不知道如何在项目里使用AspectCore(^~^,求轻拍~)。下面就来讲一下如何在IoC环境和非IoC环境里使用AspectCore的AOP。
    首先通过nuget获取AspectCore:

    Install-Package AspectCore.Core
    

    AspectCore中动态代理api在AspectCore.DynamicProxy命名空间中,所以我们需要先引入命名空间

    using AspectCore.DynamicProxy;
    

    在非IoC环境中,只使用AOP的话,AspectCore提供了ProxyGeneratorBuilder作为代理生成器创建的入口

    ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
    IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();
    

    IProxyGenerator提供了CreateClassProxy方法创建class代理和CreateInterfaceProxy方法创建interface代理,创建的代理类被定义在命名为AspectCore.DynamicProxy.Generator的动态程序集中,并且代理类使用AspectCore.DynamicGenerated命名空间。
    我们先来定义一个简单的拦截器,接着定义一个interface和它的简单实现,并创建interface的代理:

    class Program
    {
        static void Main(string[] args)
        {
            ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
            IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build();
            SampleInterface sampleInterface = proxyGenerator.CreateInterfaceProxy<SampleInterface,SampleClass>();
            Console.WriteLine(sampleInterface);
            sampleInterface.Foo();
            Console.ReadKey();
        }
    }
    
    public class SampleInterceptor : AbstractInterceptorAttribute
    {
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            Console.WriteLine("call interceptor");
            return context.Invoke(next);
        }
    }
    
    public class SampleClass : SampleInterface
    {
        public virtual void Foo() { }
    }
    
    [SampleInterceptor]
    public interface SampleInterface
    {
        void Foo();
    }
    
    

    将会输出:

    AspectCore.DynamicGenerated.SampleInterface1
    call interceptor
    

    同时,IProxyGenerator提供了若干重载的扩展方法来创建已有类或接口实例的代理,可在ProxyGeneratorExtensions中找到并使用它们。

    在IoC中使用AspectCore.DynamicProxy

    AspectCore在设计之初就考虑AOP和IoC的集成使用,并提供AOP抽象接口以兼容不同IoC,目前已实现和AspectCore.DynamicProxy集成的IoC框架有:

    • AspectCore.Injector(AspectCore Framework的内置IoC)
    • Microsoft.Extensions.DependencyInjection(Asp.Net Core的内置DI框架)
    • Autofac

    下面我们分别看一下在三个IoC中如何使用AspectCore.DynamicProxy。

    AspectCore.Injector

    AspectCore.Injector中内置了对AspectCore.DynamicProxy的支持,所以我们可以直接使用它:

    IServiceContainer serviceContainer = new ServiceContainer();
    serviceContainer.AddType<SampleInterface, SampleClass>();
    IServiceResolver serviceResolver = serviceContainer.Build();
    SampleInterface sampleInterface = serviceResolver.Resolve<SampleInterface>();
    Console.WriteLine(sampleInterface);
    sampleInterface.Foo();
    

    输出:

    AspectCore.DynamicGenerated.SampleClass
    call interceptor
    

    Microsoft.Extensions.DependencyInjection

    AspectCore提供AspectCore.Extensions.DependencyInjection包集成Microsoft.Extensions.DependencyInjection和AspectCore.DynamicProxy。
    通过nuget获取:

    Install-Package AspectCore.Extensions.DependencyInjection
    

    AspectCore提供了针对IServiceCollection的扩展方法AddDynamicProxy注册动态代理的接口和相关拦截器配置,并需要使用BuildAspectCoreServiceProvider创建被DynamicProxy接管的ServiceProvider:

    IServiceCollection services = new ServiceCollection();
    services.AddTransient<SampleInterface, SampleClass>();
    
    services.AddDynamicProxy();
    IServiceProvider serviceProvider = services.BuildAspectCoreServiceProvider();
    
    SampleInterface sampleInterface = serviceProvider.GetService<SampleInterface>();
    Console.WriteLine(sampleInterface);
    sampleInterface.Foo();
    

    输出:

    AspectCore.DynamicGenerated.SampleClass
    call interceptor
    

    Autofac

    AspectCore提供AspectCore.Extensions.Autofac包集成Autofac和AspectCore.DynamicProxy。
    通过nuget获取:

    Install-Package AspectCore.Extensions.Autofac
    

    AspectCore提供了针对ContainerBuilder的扩展方法RegisterDynamicProxy注册动态代理的接口和相关拦截器配置

    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<SampleClass>().As<SampleInterface>();
    
    builder.RegisterDynamicProxy();
    
    var container = builder.Build();
    SampleInterface sampleInterface = container.Resolve<SampleInterface>();
    Console.WriteLine(sampleInterface);
    sampleInterface.Foo();
    

    输出:

    AspectCore.DynamicGenerated.SampleClass
    call interceptor
    

    有问题反馈

    如果您有任何问题,请提交 Issue 给我们。
    Github : https://github.com/dotnetcore/AspectCore-Framework
    AspectCore QQ群: 306531723

  • 相关阅读:
    SpringData JPA 使用原生 SQL
    解决:CannotAcquireResourceException: A ResourcePool could not acquire a resource from its primary factory or source.
    Java 正则表达式 简单用法
    Java文件I/O简单介绍
    理清 UT、UTC、GMT和CST
    【LeetCode】面试题62. 圆圈中最后剩下的数字
    【阅读笔记】Java核心技术卷一 #6.Chapter8
    【阅读笔记】Java核心技术卷一 #5.Chapter7
    【阅读笔记】Java核心技术卷一 #4.Chapter6
    SQL面试题
  • 原文地址:https://www.cnblogs.com/liuhaoyang/p/aspectcore-getting-started.html
Copyright © 2020-2023  润新知