zoukankan      html  css  js  c++  java
  • 6. abp中的拦截器

    abp拦截器基本定义

    拦截器接口定义:

    public interface IAbpInterceptor
    {
        void Intercept(IAbpMethodInvocation invocation);
    
        Task InterceptAsync(IAbpMethodInvocation invocation);
    }
    

    默认抽象类定义:

    public abstract class AbpInterceptor : IAbpInterceptor
    {
    	public abstract void Intercept(IAbpMethodInvocation invocation);
    
    	public virtual Task InterceptAsync(IAbpMethodInvocation invocation)
    	{
    		Intercept(invocation);
    		return Task.CompletedTask;
    	}
    }
    

    abp的拦截器实现是基于Autofac.Extras.DynamicProxy,这个包依赖两个组件:Autofac、Castle.Core(实质上是调用内部组件DynamicProxy实现动态代理)。关于此组件的资料参考

    .NET 通过 Autofac 和 DynamicProxy 实现AOP

    Type Interceptors

    Abp拦截器的设计轨迹

    此类的作用就是将aspnetcore默认的DI服务容器(ServiceCollection)替换为Autofac。

    public static IServiceProvider BuildServiceProviderFromFactory<TContainerBuilder>([NotNull] this IServiceCollection services, Action<TContainerBuilder> builderAction = null)
    {
        Check.NotNull(services, nameof(services));
    
        var serviceProviderFactory = services.GetSingletonInstanceOrNull<IServiceProviderFactory<TContainerBuilder>>();
        if (serviceProviderFactory == null)
        {
    	    throw new AbpException($"Could not find {typeof(IServiceProviderFactory<TContainerBuilder>).FullName} in {services}.");
        }
    
        var builder = serviceProviderFactory.CreateBuilder(services);
        builderAction?.Invoke(builder);
        return serviceProviderFactory.CreateServiceProvider(builder);
    }
    

    CreateBuilder函数源码:

    /// <summary>
    /// Creates a container builder from an <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
    /// </summary>
    /// <param name="services">The collection of services</param>
    /// <returns>A container builder that can be used to create an <see cref="T:System.IServiceProvider" />.</returns>
    public ContainerBuilder CreateBuilder(IServiceCollection services)
    {
        _services = services;
        
        _builder.Populate(services);
        
        return _builder;
    }
    

    Populate函数源码:

    public static void Populate(
            this ContainerBuilder builder,
            IServiceCollection services)
    {
        builder.RegisterType<AutofacServiceProvider>().As<IServiceProvider>();
        builder.RegisterType<AutofacServiceScopeFactory>().As<IServiceScopeFactory>();
    
        Register(builder, services);
    }
    

    Register函数:

    /// 注册拦截器
    private static void Register(
            ContainerBuilder builder,
            IServiceCollection services)
    {
        var moduleContainer = services.GetSingletonInstance<IModuleContainer>();
        var registrationActionList = services.GetRegistrationActionList();
    
        // 遍历DI服务容器中的服务
        foreach (var service in services)
        {
            if (service.ImplementationType != null)
            {
                // 判断服务是否是泛型
                var serviceTypeInfo = service.ServiceType.GetTypeInfo();
                if (serviceTypeInfo.IsGenericTypeDefinition)
                {
                    builder
                        .RegisterGeneric(service.ImplementationType)
                        .As(service.ServiceType)
                        .ConfigureLifecycle(service.Lifetime)
                        .ConfigureAbpConventions(moduleContainer, registrationActionList);
                }
                else
                {
                    builder
                        .RegisterType(service.ImplementationType)
                        .As(service.ServiceType)
                        .ConfigureLifecycle(service.Lifetime)
                        .ConfigureAbpConventions(moduleContainer, registrationActionList);
                }
            }
            // 其余实现
            ......
        }
    }
    

    ConfigureAbpConventions函数源码:

    public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> ConfigureAbpConventions<TLimit, TActivatorData, TRegistrationStyle>(
        this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registrationBuilder, 
        IModuleContainer moduleContainer, 
        ServiceRegistrationActionList registrationActionList)
    where TActivatorData : ReflectionActivatorData
    {
        // 其余实现
        .....
        
        // 这里就是调用OnRegistred函数里面的Action委托
        registrationBuilder = registrationBuilder.InvokeRegistrationActions(registrationActionList, serviceType, implementationType);
    
        return registrationBuilder;
    }
    

    InvokeRegistrationActions函数源码:

    private static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InvokeRegistrationActions<TLimit, TActivatorData, TRegistrationStyle>(this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registrationBuilder, ServiceRegistrationActionList registrationActionList, Type serviceType, Type implementationType) 
        where TActivatorData : ReflectionActivatorData
    {
        var serviceRegistredArgs = new OnServiceRegistredContext(serviceType, implementationType);
    
        foreach (var registrationAction in registrationActionList)
        {
            // 调用OnRegistred函数里面的Action委托,注入拦截器
            registrationAction.Invoke(serviceRegistredArgs);
        }
    
        //如果有拦截器
        if (serviceRegistredArgs.Interceptors.Any())
        {
            // 在某个服务类型(ServiceType)类上注册拦截器
            registrationBuilder = registrationBuilder.AddInterceptors(
                serviceType,
                serviceRegistredArgs.Interceptors
            );
        }
    
        return registrationBuilder;
    }
    

    AddInterceptors函数源码:

    private static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> AddInterceptors<TLimit, TActivatorData, TRegistrationStyle>(
        this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registrationBuilder, 
        Type serviceType,
        IEnumerable<Type> interceptors)
        where TActivatorData : ReflectionActivatorData
        {
            // 启用拦截器
            // 如果是接口类型,那么动态创建一个接口代理
            // 否则 创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法
            if (serviceType.IsInterface)
            {
                registrationBuilder = registrationBuilder.EnableInterfaceInterceptors();
            }
            else
            {
                (registrationBuilder as IRegistrationBuilder<TLimit, ConcreteReflectionActivatorData, TRegistrationStyle>)?.EnableClassInterceptors();
            }
        
            foreach (var interceptor in interceptors)
            {
                // 动态注入拦截器,指定拦截器类型为传入的拦截器
                registrationBuilder.InterceptedBy(
                   typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptor)
                );
            }
        
            return registrationBuilder;
        }
    

    CastleAbpInterceptorAdapter是Castle.Core库通过适配器来定义了一个标准、针对IAbpInterceptor的实现。源码:

    // 泛型拦截器为 基于AbpIterceptor的拦截器类型
    public class CastleAbpInterceptorAdapter<TInterceptor> : IInterceptor
        where TInterceptor : IAbpInterceptor
    {
        private static readonly MethodInfo MethodExecuteWithoutReturnValueAsync =
            typeof(CastleAbpInterceptorAdapter<TInterceptor>)
                .GetMethod(
                    nameof(ExecuteWithoutReturnValueAsync),
                    BindingFlags.NonPublic | BindingFlags.Instance
                );
    
        private static readonly MethodInfo MethodExecuteWithReturnValueAsync =
            typeof(CastleAbpInterceptorAdapter<TInterceptor>)
                .GetMethod(
                    nameof(ExecuteWithReturnValueAsync),
                    BindingFlags.NonPublic | BindingFlags.Instance
                );
    
        // 这里的TInterceptor就是在InterceptedBy方法那里传入的拦截器类型
        // 也就是我们基于AbpInterceptor抽象类创建的拦截器
        private readonly TInterceptor _abpInterceptor;
    
        public CastleAbpInterceptorAdapter(TInterceptor abpInterceptor)
        {
            _abpInterceptor = abpInterceptor;
        }
        
        // 其余代码
    }
    

    IAbpMethodInvocation接口封装了被拦截方法调用时的各种参数,例如,被拦截方法在调用时所传递的参数,返回值类型,方法定义等。Castle.Core库通过适配器来定义了一个标准、针对IAbpMethodInvocation的实现。源码:

    public class CastleAbpMethodInvocationAdapter : IAbpMethodInvocation
    {
        public object[] Arguments => Invocation.Arguments;
    
        public IReadOnlyDictionary<string, object> ArgumentsDictionary => _lazyArgumentsDictionary.Value;
        private readonly Lazy<IReadOnlyDictionary<string, object>> _lazyArgumentsDictionary;
    
        public Type[] GenericArguments => Invocation.GenericArguments;
    
        public object TargetObject => Invocation.InvocationTarget ?? Invocation.MethodInvocationTarget;
    
        public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method;
    
        public object ReturnValue
        {
            get => _actualReturnValue ?? Invocation.ReturnValue;
            set => Invocation.ReturnValue = value;
        }
    
        private object _actualReturnValue;
    
        protected IInvocation Invocation { get; }
        protected IInvocationProceedInfo ProceedInfo { get; }
    
        public CastleAbpMethodInvocationAdapter(IInvocation invocation, IInvocationProceedInfo proceedInfo)
        {
            Invocation = invocation;
            ProceedInfo = proceedInfo;
    
            _lazyArgumentsDictionary = new Lazy<IReadOnlyDictionary<string, object>>(GetArgumentsDictionary);
        }
    
        // 内部调用 Castle.DynamicProxy
        public void Proceed()
        {
            // 省略实现
        }
    
        public Task ProceedAsync()
        {
            // 省略实现
        }
    
        private IReadOnlyDictionary<string, object> GetArgumentsDictionary()
        {
            // 省略实现
        }
    }
    

    CastleAbpMethodInvocationAdapter适配器的调用处在CastleAbpInterceptorAdapter适配器类的Intercept函数:

    // 调用自定义、基于AbpInterceptor的拦截器
    private void InterceptSyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo)
    {
        _abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation, proceedInfo));
    }
    

    参考:[Abp vNext 源码分析] - 3. 依赖注入与拦截器

  • 相关阅读:
    cha[] strrev(char[])
    线段树入门了解
    求最大严格递增序列
    素数环
    20181016-10 每周例行报告
    第五周例行报告
    作业要求 20180925-1 每周例行报告
    作业要求20180925-2 功能测试
    作业要求 20180925-3 效能分析
    作业要求20180925-4 单元测试,结对
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/11965930.html
Copyright © 2011-2022 走看看