一、简要说明
本篇文章主要剖析与讲解 Abp vNext 在 Web API 项目下的启动流程,让大家了解整个 Abp vNext 框架是如何运作的。总的来说 ,Abp vNext 比起 ABP 框架更加精简。因为在 vNext 版本当中,原来归属于 Abp 库的许多内置的基本组件 (组织单元、拦截器等) 被拆分成了单独的模块,这样我们来看它整个启动流程就更加地直观清晰。
二、源码分析
要分析其源码,我这里是从他官方的 Demo 模板入手的,你可以在 https://abp.io 上构建你自己的模板项目。工具上我使用的是 Jetbrains 家的 Rider,配置好符号服务器(External Symbols Server),我们就能够直接调试其底层源码。(因为 Abp vNext 项目使用了 Source Link)
2.1 Startup 文件的入口点
这里我选择的项目是 Web API,直接来到其 Startup.cs
文件,我们就可以看到在 Startup
类当中的 Configure()
与 ConfigureService()
方法内部我们注入并启用了 Abp vNext 框架。
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// 注入 Abp 相关的服务。
services.AddApplication<DemoAppModule>(options =>
{
options.UseAutofac();
});
// 接管自带的 IoC Container。
return services.BuildServiceProviderFromFactory();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// 配置 ASP.NET Core Mvc 相关参数。
app.InitializeApplication();
}
}
在上面我们可以看到,ABP vNext 在注入服务的时候支持传入一个 Action<AbpApplicationCreationOptions>
委托。上述代码中,这个委托内部使用了 UseAutoFac()
将 AutoFac 的容器注入到了 MS IoC 当中,关于这块代码下文会着重讲解。
2.2 Abp 服务注册
在上一节看到的服务注册代码,是通过扩展 IServiceCollection
接口编写的一个扩展方法实现的,在方法内部是通过 AbpApplicationFactory
静态工厂来创建一个 AbpApplicationBase
实例。
public static class ServiceCollectionApplicationExtensions
{
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>(
[NotNull] this IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
where TStartupModule : IAbpModule
{
return AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);
}
// ... 其他代码
}
在这个方法当中,通过名字 WithExternalServiceProvider 我们就知道,这个 Applictaion 是依赖于外部的 IServiceProvider
实例。
提示:
它继承的
AbpApplicationBase
基类还拥有另外一个实现,即AbpApplicationWithInternalServiceProvider
类型,该类型一般 用于控制台程序,它会在 Abp vNext 框架内自行构建一个IServiceProvider
对象。
我们回到之前的代码,在这个 AbpApplicationWithExternalServiceProvider
类型内部的构造方法很简单,只是通过 IServiceCollection
对象把自己注入到了服务集合当中。
internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase, IAbpApplicationWithExternalServiceProvider
{
public AbpApplicationWithExternalServiceProvider(
[NotNull] Type startupModuleType,
[NotNull] IServiceCollection services,
[CanBeNull] Action<AbpApplicationCreationOptions> optionsAction
) : base(
startupModuleType,
services,
optionsAction)
{
// 注入自己到 IoC 当中。
services.AddSingleton<IAbpApplicationWithExternalServiceProvider>(this);
}
// 执行框架初始化操作,主要工作是加载模块并执行其初始化方法。
public void Initialize(IServiceProvider serviceProvider)
{
Check.NotNull(serviceProvider, nameof(serviceProvider));
SetServiceProvider(serviceProvider);
InitializeModules();
}
}
重点代码在于它的基类构造函数,在基类构造函数当中 Abp vNext 注入了诸多 ASP.NET Core 需要的日志服务、本地化服务等。并且它也抽象出了一个 IModuleLoader
,用于辅助我们加载模块。
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;
// 添加一个空的对象访问器,该访问器的值会在初始化的时候被赋值。
s