攔截器接口定義:html
public interface IAbpInterceptor { void Intercept(IAbpMethodInvocation invocation); Task InterceptAsync(IAbpMethodInvocation invocation); }
默認抽象類定義:ide
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源碼分析
此類的做用就是將aspnetcore默認的DI服務容器(ServiceCollection)替換爲Autofac。this
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函數:code
/// 註冊攔截器 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函數源碼:htm
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)); }