一、概述 Abp
是一个开源应用程序框架,专注于基于 ASP.NET Core
的 Web 应用程序开发,但也支持开发其他类型的应用程序。 本文先分析相关的几个类型,再分析 Abp 的启动流程。
二、AbpApplication 这里的 Application
并非领域驱动设计( DDD
)的应用程序层。Abp 是一个框架,运行于 .Net Core 之上;AbpApplication
是一个应用,运行于 Abp 之上 。AbpApplication 主要负责模块的加载和卸载。 从代码上看,Application 是实现了 IAbpApplication
接口的类,有三个实现了 IAbpApplication 接口的类,继承关系见下图。
1 2 3 4 5 graph BT D[AbpApplicationWithExternalServiceProvider] --> C[AbpApplicationBase] E[AbpApplicationWithInternalServiceProvider] --> C[AbpApplicationBase] C --> B[IAbpApplication] B --> A[IModuleContainer]
AbpApplicationBase
是抽象类。AbpApplicationWithExternalServiceProvider
一般用于 AspNetCore
应用,使用 AspNetCore 的 service collection 创建 service provider;而 AbpApplicationWithInternalServiceProvider
一般用于其他应用,使用自建的 service collection 创建 service provider 。 另外,IAbpApplication
接口继承了 IModuleContainer
接口,后者定义了一个 IAbpModuleDescriptor
元素的只读集合。
三、IModuleContainer 和 IAbpModuleDescriptor 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 namespace Volo.Abp.Modularity { public interface IModuleContainer { [NotNull ] IReadOnlyList<IAbpModuleDescriptor> Modules { get ; } } } namespace Volo.Abp.Modularity { public interface IAbpModuleDescriptor { Type Type { get ; } Assembly Assembly { get ; } IAbpModule Instance { get ; } bool IsLoadedAsPlugIn { get ; } IReadOnlyList<IAbpModuleDescriptor> Dependencies { get ; } } }
IAbpModuleDescriptor
用于保存应用包含的模块的类型、所在程序集、实例、是否以插件形式加载和依赖的其他模块。其实模块的类型和所在程序集是冗余的,通过实例对象也可以获取到。
IsLoadedAsPlugIn 表示模块是否已插件形式加载。以插件形式加载的目的在这里不做分析。不过,一个以插件形式加载的模块,会创建两个 AbpModuleDescriptor
实例。
四、IAbpApplication 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 namespace Volo.Abp { public interface IAbpApplication : IModuleContainer , IDisposable { Type StartupModuleType { get ; } IServiceCollection Services { get ; } IServiceProvider ServiceProvider { get ; } void Shutdown () ; } }
StartupModuleType
属性用于模块加载时查找应用依赖的其他模块。Services
属性用于将 AbpApplication 自身注册为 IoC 单例,以及设置 ServiceProvider
属性。ServiceProvider
属性当然用于从 IoC 中获取实例。其引用应用使用的根 service provider 。在应用初始化之前不能使用。Shutdown
方法用于正常关闭应用程序和所有模块。
五、AbpApplicationBase 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 namespace Volo.Abp { public abstract class AbpApplicationBase : IAbpApplication { [NotNull ] public Type StartupModuleType { get ; } public IServiceProvider ServiceProvider { get ; private set ; } public IServiceCollection Services { get ; } public IReadOnlyList<IAbpModuleDescriptor> Modules { get ; } internal AbpApplicationBase ( [NotNull] Type startupModuleType, [NotNull] IServiceCollection services, [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction ) { Check.NotNull(startupModuleType, nameof (startupModuleType)); Check.NotNull(services, nameof (services)); StartupModuleType = startupModuleType; Services = services; services.TryAddObjectAccessor<IServiceProvider>(); var options = new AbpApplicationCreationOptions(services); optionsAction?.Invoke(options); services.AddSingleton<IAbpApplication>(this ); services.AddSingleton<IModuleContainer>(this ); services.AddCoreServices(); services.AddCoreAbpServices(this , options); Modules = LoadModules(services, options); } public virtual void Shutdown () { using (var scope = ServiceProvider.CreateScope()) { scope.ServiceProvider .GetRequiredService<IModuleManager>() .ShutdownModules(new ApplicationShutdownContext(scope.ServiceProvider)); } } public virtual void Dispose () { } protected virtual void SetServiceProvider (IServiceProvider serviceProvider ) { ServiceProvider = serviceProvider; ServiceProvider.GetRequiredService<ObjectAccessor<IServiceProvider>>().Value = ServiceProvider; } protected virtual void InitializeModules () { using (var scope = ServiceProvider.CreateScope()) { scope.ServiceProvider .GetRequiredService<IModuleManager>() .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider)); } } private IReadOnlyList <IAbpModuleDescriptor > LoadModules (IServiceCollection services, AbpApplicationCreationOptions options ) { return services .GetSingletonInstance<IModuleLoader>() .LoadModules( services, StartupModuleType, options.PlugInSources ); } } }
相关类型: ObjectAccessor ApplicationShutdownContext IModuleManager IModuleLoader
六、AbpApplicationWithExternalServiceProvider 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 namespace Volo.Abp { internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase , IAbpApplicationWithExternalServiceProvider { public AbpApplicationWithExternalServiceProvider ( [NotNull] Type startupModuleType, [NotNull] IServiceCollection services, [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction ) : base ( startupModuleType, services, optionsAction ) { services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this ); } public void Initialize (IServiceProvider serviceProvider ) { Check.NotNull(serviceProvider, nameof (serviceProvider)); SetServiceProvider(serviceProvider); InitializeModules(); } } }
七、AbpApplicationWithInternalServiceProvider 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 namespace Volo.Abp { internal class AbpApplicationWithInternalServiceProvider : AbpApplicationBase , IAbpApplicationWithInternalServiceProvider { public IServiceScope ServiceScope { get ; private set ; } public AbpApplicationWithInternalServiceProvider ( [NotNull] Type startupModuleType, [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction ) : this ( startupModuleType, new ServiceCollection( ), optionsAction) { } private AbpApplicationWithInternalServiceProvider ( [NotNull] Type startupModuleType, [NotNull] IServiceCollection services, [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction ) : base ( startupModuleType, services, optionsAction ) { Services.AddSingleton<IAbpApplicationWithInternalServiceProvider>(this ); } public void Initialize () { ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope(); SetServiceProvider(serviceProvider); InitializeModules(); } public override void Dispose () { base .Dispose(); ServiceScope.Dispose(); } } }
八、Abp AspNetCore 应用的启动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Startup { public IServiceProvider ConfigureServices (IServiceCollection services ) { services.AddApplication<BookStoreWebModule>(options => { options.UseAutofac(); }); return services.BuildServiceProviderFromFactory(); } public void Configure (IApplicationBuilder app, ILoggerFactory loggerFactory ) { app.InitializeApplication(); } }
ConfigureServices
方法可以无返回值或返回 IServiceProvider。如果用 .NET Core CLI
创建 AspNetCore 应用,ConfigureServices
方法默认无返回值的,这种情况会尝试其他方式来创建 service provider(详见:StartupLoader
)。Abp 决定自行构建 service provider 。UseAutofac
会创建一个能够产出 service provider ( AutofacServiceProvider
) 的 AbpAutofacServiceProviderFactory
对象,将其以单例形式注册到 IoC 容器中。BuildServiceProviderFromFactory
找到 AbpAutofacServiceProviderFactory 并产出 AutofacServiceProvider
对象。BookStoreWebModule
是一个 AbpModule。与其他模块不同的是,该模块是启动模块。
InitializeApplication
扩展方法主要调用 IAbpApplicationWithExternalServiceProvider
的 Initialize
方法。核心作用就是初始化模块。
总之,在执行 Startup 的 ConfigureServices 方法时加载模块,在执行 Configure 方法时初始化模块。
参考资料