ABPvnext源碼分析 (二):Autofac整合及動態代理

寫在前面:

上一篇咱們講了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攔截器的轉換。

相關文章
相關標籤/搜索