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. 依赖注入与拦截器

6. abp中的拦截器的更多相关文章

  1. ABP中的拦截器之ValidationInterceptor(上)

    从今天这一节起就要深入到ABP中的每一个重要的知识点来一步步进行分析,在进行介绍ABP中的拦截器之前我们先要有个概念,到底什么是拦截器,在介绍这些之前,我们必须要了解AOP编程思想,这个一般翻译是面向 ...

  2. 5.Struts2中的拦截器

    拦截器是Struts2中的核心,其自带很多很多的拦截器,这里主要介绍一下自定义拦截器,恩多一半情况下呢?我们不需要使用到自定义的拦截器,Struts2本身已经提 供了很多的拦截器供我们使用,对于自定义 ...

  3. 9.springMVC中的拦截器

    springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...

  4. 十五、struts2中的拦截器(框架功能核心)

    十五.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 功能是一回事. 过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面 ...

  5. spring mvc中的拦截器小结 .

    在spring mvc中,拦截器其实比较简单了,下面简单小结并demo下. preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Control ...

  6. AspectCore动态代理中的拦截器详解(一)

    前言 在上一篇文章使用AspectCore动态代理中,简单说明了AspectCore.DynamicProxy的使用方式,由于介绍的比较浅显,也有不少同学留言询问拦截器的配置,那么在这篇文章中,我们来 ...

  7. struts2中的拦截器

    一  AOP思想: 面向切面编程的思想 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP ...

  8. 系统开发中使用拦截器校验是否登录并使用MD5对用户登录密码进行加密

    项目名称:客户管理系统 项目描述: 项目基于javaEE平台,B/S模式开发.使用Struts2.Hibernate/Spring进行项目框架搭建.使用Struts中的Action 控制器进行用户访问 ...

  9. (转)spring中的拦截器(HandlerInterceptor+MethodInterceptor)

    1.  过滤器跟拦截器的区别 在说拦截器之前,不得不说一下过滤器,有时候往往被这两个词搞的头大. 其实我们最先接触的就是过滤器,还记得web.xml中配置的<filter>吗~ 你应该知道 ...

随机推荐

  1. 结合开源软件kaptcha讲解登录验证码功能的实现

    一.验证码生成之配置使用kaptcha 使用google开源的验证码实现类库kaptcha,通过maven坐标引入 <dependency> <groupId>com.gith ...

  2. C#笔记01——注释、进制、基本数据类型、量和输入输出函数

    一.注释 1.单行注释 使用方法:行首加 ” //“: VS2019中的快捷键(以后如果不特加说明都是VS2019): 注释(CTRL+E,C): 取消注释(CTRL+E,U): 2.多行注释 使用方 ...

  3. nginx离线部署脚本

    #! /bin/bashbasepath=$(cd `dirname $0`; pwd)nginx_path=/usr/localfile_name=nginxecho "--------- ...

  4. Spring Cloud - Zuul添加过滤器

    Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的. 一.过滤器方法的作用 想要使用Zuul实现过滤功能,我们需要自定义一个类继承ZuulFi ...

  5. 转载 :c# 获取net framework 版本(Environment 类)

    源链接:http://www.cnblogs.com/tobecrazy/p/3362446.html 根据自己使用情况,添加了部分备注 1.获取当前操作系统版本信息 使用Environment.OS ...

  6. 6. 彤哥说netty系列之Java NIO核心组件之Buffer

    --日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第六篇. 简介 上一章我们一起学习了Java NIO的核心组件Channel,它可以看作是实体与实体之间的连接,而且需要与Buffer交 ...

  7. 新手学分布式 - Envoy Proxy XDS Server动态配置的一点使用心得

    Envoy Proxy 动态API的使用总结 Envoy Proxy和其它L4/L7反向搭理工具最大的区别就是原生支持动态配置. 首先来看一下Envoy的大致架构 从上图可以简单理解:Listener ...

  8. Python高级数据结构-Collections模块

    在Python数据类型方法精心整理,不必死记硬背,看看源码一切都有了之中,认识了python基本的数据类型和数据结构,现在认识一个高级的:Collections 这个模块对上面的数据结构做了封装,增加 ...

  9. Android DataBinding不能自动生成ViewDataBinding类的解决方法

    如果Build.gradle和Layout文件配置正确,仍无法生成ViewDataBinding类. 经测试,Gradle的sync无效,clean project无效,invalidate and ...

  10. 工作流Activity组件值数据传递获取问题

    如图:先简单说一下大致过程 通过具体的菜单节点,加载具体的指令组件.本着低耦合的原件,需要将核查组件从指令组件重拆分出来,作为单独的组件根据业务需要拖拽到指令组件中.但是具体业务方面核查组件一方面需要 ...