上一篇咱們講了Abp的核心模塊,這一篇咱們把DI 的serviceProvider替換成Autofac,另外添加動態代理攔截器功能。動態代理指從DI容器獲取組件實例時組件實例不是原實例,而是代理實例。代理實例是對原實例進行了封裝, 在實例方法先後添加邏輯處理,讓獲取的對象表現基於應有對象但又有本身的邏輯。舉個例子,代理對象方法能夠在原方法先後記錄時間戳,來分析原方法的處理時長。Abp Core默認使用的是微軟官方的DI實現, 那個功能較簡單沒有代理功能,爲了添加動態代理功能,咱們把DI實現替換爲Autofac,並使用Autofac集成的代理實現方式Castle Core。
集成Autofac,咱們須要添加Volo.Abp.Autofac包,這個包自己是Abp模塊,其依賴AbpCastleCoreModule模塊(Volo.Abp.CatleCore)html
namespace Volo.Abp.Autofac { [DependsOn(typeof(AbpCastleCoreModule))] public class AbpAutofacModule : AbpModule { } }
因此咱們添加Volo.Abp.Autofac包並讓咱們的應用模塊DependsOn(typeof(AbpAutofacModule))就自動的把AbpAutofacModule,AbpCastleCoreModule加入到咱們的Core中進行模塊管理,也就是說那些基於約定的服務會自動註冊到咱們的abpApplication.Services中,很是的方便。咱們在使用Abp中發現好多第三方庫都有對應的Volo.Abp.Xxx包也是這個道理,經過把包加入咱們Abp的模塊管理體系,把各自的服務註冊放入各自的包當中,這樣咱們的應用代碼就不須要一個一個的註冊這些三方庫服務,應用模塊直接添加DependsOn(typeof(Xxx))便可。api
Abp集成Autofac很是簡單 var application = services.AddApplication<TStartupModule>(option=>options.UseAutofac(););
咱們看下UseAutofac這個方法app
public static void UseAutofac(this AbpApplicationCreationOptions options) { var builder = new ContainerBuilder(); options.Services.AddObjectAccessor(builder); options.Services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder)); }
回憶上一篇最後的代碼,因爲註冊了IServiceProviderFactory<ContainerBuilder>,因而使用該實例serviceProviderFactory的工廠方法serviceProviderFactory.CreateServiceProvider(serviceProviderFactory.CreateBuilder(services)完成DI容器IServiceProvider的建立,這就把DI容器具體的建立邏輯交給了AbpAutofacServiceProviderFactory,很是巧妙的設計。ide
public ContainerBuilder CreateBuilder(IServiceCollection services) { _services = services; _builder.Populate(services); return _builder; }
在AbpAutofacServiceProviderFactory中CreateBuilder調用了方法_builder.Populate(services);注意這裏的Populate方法是
Autofac.Extensions.DependencyInjection.AutofacRegistration.Populate,
從新實現了Autofac的同名擴展方法 Microsoft.Extensions.DependencyInjection.AutofacRegistration.Populateui
,他和原擴展方法相似但加入了新的邏輯,咱們不要引用錯誤包。this
跟蹤其實現spa
public static void Populate( this ContainerBuilder builder, IServiceCollection services) { builder.RegisterType<AutofacServiceProvider>().As<IServiceProvider>(); builder.RegisterType<AutofacServiceScopeFactory>().As<IServiceScopeFactory>(); //註冊IServiceProvider,IServiceScopeFactory Register(builder, services); }
private static void Register( ContainerBuilder builder, IServiceCollection services) { var moduleContainer = services.GetSingletonInstance<IModuleContainer>(); //植入的內容 var registrationActionList = services.GetRegistrationActionList(); //植入的內容 foreach (var service in services) { if (service.ImplementationType != null) { // Test if the an open generic type is being registered var serviceTypeInfo = service.ServiceType.GetTypeInfo(); if (serviceTypeInfo.IsGenericTypeDefinition) //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); //這一步是新添加的邏輯 包含攔截器 } } else if (service.ImplementationFactory != null) { var registration = RegistrationBuilder.ForDelegate(service.ServiceType, (context, parameters) => { var serviceProvider = context.Resolve<IServiceProvider>(); return service.ImplementationFactory(serviceProvider); }) .ConfigureLifecycle(service.Lifetime) .CreateRegistration(); //TODO: ConfigureAbpConventions ? builder.RegisterComponent(registration); } else { builder .RegisterInstance(service.ImplementationInstance) .As(service.ServiceType) .ConfigureLifecycle(service.Lifetime); } } }
其主要邏輯是把serives中每個服務註冊在builder中註冊。其中對每一個服務還調用了ConfigureAbpConventions(moduleContainer, registrationActionList)設計
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> ConfigureAbpConventions<TLimit, TActivatorData, TRegistrationStyle>( //builder.Populate(services)植入的ABP部分 this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registrationBuilder, IModuleContainer moduleContainer, ServiceRegistrationActionList registrationActionList) where TActivatorData : ReflectionActivatorData { var serviceType = registrationBuilder.RegistrationData.Services.OfType<IServiceWithType>().FirstOrDefault()?.ServiceType; if (serviceType == null) { return registrationBuilder; //直接返回 } var implementationType = registrationBuilder.ActivatorData.ImplementationType; if (implementationType == null) { return registrationBuilder; //沒有實現類型 直接返回 } registrationBuilder = registrationBuilder.EnablePropertyInjection(moduleContainer, implementationType); //當前type程序集包含Abp模塊則開啓屬性注入 registrationBuilder = registrationBuilder.InvokeRegistrationActions(registrationActionList, serviceType, implementationType); //調用registration HOOK 若是有攔截器,則添加攔截器 return registrationBuilder; }
上面serviceType是Autofac的registrationBuilder添加的元數據咱們沒必要理會,implementationType是組件(服務實例)類型。重點咱們跟蹤下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) //執行每個registrationAction { registrationAction.Invoke(serviceRegistredArgs); } if (serviceRegistredArgs.Interceptors.Any()) //IMPORTANT 若是有攔截器,則添加攔截器 { registrationBuilder = registrationBuilder.AddInterceptors( serviceType, serviceRegistredArgs.Interceptors ); } return registrationBuilder; }
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( //https://www.cnblogs.com/stulzq/p/8547839.html autofac的動態代理 Autofac.Extras.DynamicProxy程序集 typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptor) //範型類型實例化 ABP攔截器轉CASTLE攔截器 ); } return registrationBuilder; }
動態代理實現使用的是Castle.Core的api中 code
public static IRegistrationBuilder<TLimit, TActivatorData, TStyle> InterceptedBy<TLimit, TActivatorData, TStyle>( this IRegistrationBuilder<TLimit, TActivatorData, TStyle> builder, params Type[] interceptorServiceTypes)
其中interceptorServiceTypes爲IInterceptor的類型的Type。咱們Abp使用的是IAbpInterceptor。 CastleAbpInterceptorAdapter類就是實現從IAbpInterceptor到IInterceptor的適配。
public void Intercept(IInvocation invocation) //攔截器業務邏輯 Castle 的攔截器有一個 Intercept() 方法,該方法將在被攔截方法執行的時候觸發。 { var proceedInfo = invocation.CaptureProceedInfo(); var method = invocation.MethodInvocationTarget ?? invocation.Method;// MethodInvocationTarget目標類方法的methodInfo, Method代理方法的methodInfo if (method.IsAsync()) { InterceptAsyncMethod(invocation, proceedInfo); } else { InterceptSyncMethod(invocation, proceedInfo); } }
private void InterceptSyncMethod(IInvocation invocation, IInvocationProceedInfo proceedInfo) { _abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)); }
看一下CastleAbpInterceptorAdapter類型的Intercept方法,又調用的是_abpInterceptor.Intercept方法。
由上面能夠看出。咱們是經過CastleAbpInterceptorAdapter完成從castle core攔截器到abp攔截器的適配。 咱們定義好apb攔截器,abp自動爲咱們生成對應的castle core攔截器進行適配,進行攔截時castle core攔截器調用咱們的apb攔截器的攔截接口void Intercept(IAbpMethodInvocation invocation);
以上是abp攔截器的實現機制。經過CastleAbpInterceptorAdapter適配層完成調用castle core攔截器到間接調用 abp攔截器的轉換。