abp攔截器基本定義 攔截器介面定義: 預設抽象類定義: abp的攔截器實現是基於Autofac.Extras.DynamicProxy,這個包依賴兩個組件:Autofac、Castle.Core(實質上是調用內部組件DynamicProxy實現動態代理)。關於此組件的資料參考 ".NET 通過 A ...
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. 依賴註入與攔截器