首页 > 其他 > 详细

ABPvnext源码分析 (二):Autofac整合及动态代理

时间:2019-11-05 12:07:57      阅读:412      评论:0      收藏:0      [点我收藏+]

写在前面:

上一篇我们讲了Abp的核心模块,这一篇我们把DI 的serviceProvider替换成Autofac,另外添加动态代理拦截器功能。动态代理指从DI容器获取组件实例时组件实例不是原实例,而是代理实例。代理实例是对原实例进行了封装, 在实例方法前后添加逻辑处理,让获取的对象表现基于应有对象但又有自己的逻辑。举个例子,代理对象方法可以在原方法前后记录时间戳,来分析原方法的处理时长。Abp Core默认使用的是微软官方的DI实现, 那个功能较简单没有代理功能,为了添加动态代理功能,我们把DI实现替换为Autofac,并使用Autofac集成的代理实现方式Castle Core。
集成Autofac,我们需要添加Volo.Abp.Autofac包,这个包本身是Abp模块,其依赖AbpCastleCoreModule模块(Volo.Abp.CatleCore)

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))即可。

 

正菜开始:

Abp集成Autofac非常简单 var application = services.AddApplication<TStartupModule>(option=>options.UseAutofac(););
我们看下UseAutofac这个方法

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,非常巧妙的设计。

    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.utofacRegistration.Populate

,他和原扩展方法类似但加入的新的逻辑,我们不要引用错误包。

跟踪其实现

    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是组件(服务实例)类型。

ABPvnext源码分析 (二):Autofac整合及动态代理

原文:https://www.cnblogs.com/yilianhuaixiao/p/11796663.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!