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
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中的拦截器的更多相关文章
- ABP中的拦截器之ValidationInterceptor(上)
从今天这一节起就要深入到ABP中的每一个重要的知识点来一步步进行分析,在进行介绍ABP中的拦截器之前我们先要有个概念,到底什么是拦截器,在介绍这些之前,我们必须要了解AOP编程思想,这个一般翻译是面向 ...
- 5.Struts2中的拦截器
拦截器是Struts2中的核心,其自带很多很多的拦截器,这里主要介绍一下自定义拦截器,恩多一半情况下呢?我们不需要使用到自定义的拦截器,Struts2本身已经提 供了很多的拦截器供我们使用,对于自定义 ...
- 9.springMVC中的拦截器
springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...
- 十五、struts2中的拦截器(框架功能核心)
十五.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 功能是一回事. 过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面 ...
- spring mvc中的拦截器小结 .
在spring mvc中,拦截器其实比较简单了,下面简单小结并demo下. preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Control ...
- AspectCore动态代理中的拦截器详解(一)
前言 在上一篇文章使用AspectCore动态代理中,简单说明了AspectCore.DynamicProxy的使用方式,由于介绍的比较浅显,也有不少同学留言询问拦截器的配置,那么在这篇文章中,我们来 ...
- struts2中的拦截器
一 AOP思想: 面向切面编程的思想 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP ...
- 系统开发中使用拦截器校验是否登录并使用MD5对用户登录密码进行加密
项目名称:客户管理系统 项目描述: 项目基于javaEE平台,B/S模式开发.使用Struts2.Hibernate/Spring进行项目框架搭建.使用Struts中的Action 控制器进行用户访问 ...
- (转)spring中的拦截器(HandlerInterceptor+MethodInterceptor)
1. 过滤器跟拦截器的区别 在说拦截器之前,不得不说一下过滤器,有时候往往被这两个词搞的头大. 其实我们最先接触的就是过滤器,还记得web.xml中配置的<filter>吗~ 你应该知道 ...
随机推荐
- GitHub 标星 1.6w+,我发现了一个宝藏项目,作为编程新手有福了!
大家好,我是 Rocky0429,一个最近老在 GitHub 上闲逛的蒟蒻... 特别惭愧的是,虽然我很早就知道 GitHub,但是学会逛 GitHub 的时间特别晚.当时一方面是因为菜,看着这种全是 ...
- Photoshop CS2软件下载与安装教程
Photoshop CS2精简版下载地址: 链接:https://pan.baidu.com/s/1ryJPLuKG_MixWjGJgLebOg提取码:nzz9 软件介绍: Photoshop主要处理 ...
- 人生若只如初见---Spring概述以及环境的搭建
Spring 是什么 Spring是由Apache开发的一种轻量型Java框架,能够更加便捷使用JavaBean(之前只有EJB才能实现) Spring的主要优势:分层架构: DAO层:(Data A ...
- 折腾笔记-计蒜客T1158-和为给定数AC记
欢迎查看原题 1.简单题目叙述 蒜头君给出若干个整数,询问其中是否有一对数的和等于给定的数. 输入格式 共三行: 第一行是整数 ),表示有 n 个整数. 第二行是 n 个整数.整数的范围是在 0 到 ...
- 5分钟上手自动化测试——Airtest+Poco快速上手
版权声明:该文章为AirtestProject原创文章:允许转载,但转载必须注明“转载”并保留原链接 前言 本文档将演示使用`AirtestProject`专用的编辑器AirtestIDE,编写`Ai ...
- adb adb monkey命令及介绍
1.adb的组成部分 守护进程,客户端,服务器端` 2.Monkey程序是Google公司提供的一个压力和稳定性测试的工具 3.命令 命令 参数 功能 adb version 查看当前a ...
- STM32 GPIO口的配置和应用
STM32F103ZET6 一共有7组IO口(有FT的标识是可以识别5v的) 每组IO口有16个IO 一共16*7=112个IO 4种输入模式: (1) GPIO_Mode_AIN 模拟输入 (2) ...
- Vue-Router中History模式【华为云分享】
[摘要] vue-router的history模式的服务端支持 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端> ...
- luogu P4981 父子
题目背景 上演在各大学男生寝室的日常 :: A :A: "我没带纸,快来厕所救我!" B :B: "叫爸爸." A :A: "爸爸!" .. ...
- A*算法在最短路问题的应用及其使用举例
1 A*算法 A*算法在人工智能中是一种典型的启发式搜索算法,启发中的估价是用估价函数表示的: 其中f(n)是节点n的估价函数,g(n)表示实际状态空间中从初始节点到n节点的实际代价,h(n)是从n到 ...