日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Abp vNext 源码分析] - 1. 框架启动流程分析

發(fā)布時間:2023/12/4 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Abp vNext 源码分析] - 1. 框架启动流程分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、簡要說明

本篇文章主要剖析與講解 Abp vNext 在 Web API 項目下的啟動流程,讓大家了解整個 Abp vNext 框架是如何運作的。總的來說 ,Abp vNext 比起 ABP 框架更加精簡。因為在 vNext 版本當中,原來歸屬于 Abp 庫的許多內(nèi)置的基本組件 (組織單元、攔截器等) 被拆分成了單獨的模塊,這樣我們來看它整個啟動流程就更加地直觀清晰。

二、源碼分析

要分析其源碼,我這里是從他官方的 Demo 模板入手的,你可以在 https://abp.io 上構(gòu)建你自己的模板項目。工具上我使用的是 Jetbrains 家的 Rider,配置好符號服務(wù)器(External Symbols Server),我們就能夠直接調(diào)試其底層源碼。(因為 Abp vNext 項目使用了 Source Link)

2.1 Startup 文件的入口點

這里我選擇的項目是 Web API,直接來到其?Startup.cs?文件,我們就可以看到在?Startup?類當中的?Configure()?與?ConfigureService() 方法內(nèi)部我們注入并啟用了 Abp vNext 框架。

public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{

services.AddApplication<DemoAppModule>(options =>
{
options.UseAutofac();
});


return services.BuildServiceProviderFromFactory();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

app.InitializeApplication();
}
}

在上面我們可以看到,ABP vNext 在注入服務(wù)的時候支持傳入一個?Action<AbpApplicationCreationOptions> 委托。上述代碼中,這個委托內(nèi)部使用了 UseAutoFac() 將 AutoFac 的容器注入到了 MS IoC 當中,關(guān)于這塊代碼下文會著重講解。

2.2 Abp 服務(wù)注冊

在上一節(jié)看到的服務(wù)注冊代碼,是通過擴展?IServiceCollection?接口編寫的一個擴展方法實現(xiàn)的,在方法內(nèi)部是通過?AbpApplicationFactory?靜態(tài)工廠來創(chuàng)建一個?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?基類還擁有另外一個實現(xiàn),即?AbpApplicationWithInternalServiceProvider?類型,該類型一般?用于控制臺程序,它會在 Abp vNext 框架內(nèi)自行構(gòu)建一個?IServiceProvider 對象。

我們回到之前的代碼,在這個?AbpApplicationWithExternalServiceProvider?類型內(nèi)部的構(gòu)造方法很簡單,只是通過?IServiceCollection 對象把自己注入到了服務(wù)集合當中。

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();
}
}

重點代碼在于它的基類構(gòu)造函數(shù),在基類構(gòu)造函數(shù)當中 Abp vNext 注入了諸多 ASP.NET Core 需要的日志服務(wù)、本地化服務(wù)等。并且它也抽象出了一個 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;


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);
}

提示:

這里的對象訪問器其實就是一個占位的類型對象,這樣方面后面替換其具體實現(xiàn)。例如在上文當中的 IServiceProvider?通過?ObjectAccessor<T> 對象包裹起來,其值是 NULL,但是在后面我們可以根據(jù)自己的需要替換其具體的 Value 。

2.3 替換 IoC 容器

再回到之前調(diào)用?AddApplication<T>()?傳遞的委托方法,在其內(nèi)部我們調(diào)用了?UseAutofac() 方法。這個方法很簡單,內(nèi)部就只有三行代碼。

這三行代碼主要是初始化了一個 AutoFac 的容器構(gòu)建對象,其次注入?IServiceProviderFactory?和 Abp 的默認實現(xiàn)?AbpAutofacServiceProviderFactory 。

public static void UseAutofac(this AbpApplicationCreationOptions options)
{
var builder = new ContainerBuilder();
options.Services.AddObjectAccessor(builder);

options.Services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder));
}

這個工廠類的就是在構(gòu)建?IServiceProvider?的時候使用,即?BuildServiceProviderFromFactory() 方法。該方法內(nèi)部邏輯很簡單,就是從已經(jīng)注冊的服務(wù)集合(IServiceCollection)當中獲得之前注冊的工廠類,通過調(diào)用工廠類的?CreateServiceProvider()方法構(gòu)建?IServiceProvider,并作為返回值替換掉默認的 IoC 容器。

public static IServiceProvider BuildServiceProviderFromFactory([NotNull] this IServiceCollection services)
{
Check.NotNull(services, nameof(services));


foreach (var service in services)
{
var factoryInterface = service.ImplementationInstance?.GetType()
.GetTypeInfo()
.GetInterfaces()
.FirstOrDefault(i => i.GetTypeInfo().IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IServiceProviderFactory<>));

if (factoryInterface == null)
{
continue;
}


var containerBuilderType = factoryInterface.GenericTypeArguments[0];
return (IServiceProvider)typeof(ServiceCollectionCommonExtensions)
.GetTypeInfo()
.GetMethods()
.Single(m => m.Name == nameof(BuildServiceProviderFromFactory) && m.IsGenericMethod)
.MakeGenericMethod(containerBuilderType)
.Invoke(null, new object[] { services, null });
}

return services.BuildServiceProvider();
}


public static IServiceProvider BuildServiceProviderFromFactory<TContainerBuilder>([NotNull] this IServiceCollection services, Action<TContainerBuilder> builderAction = null)
{
Check.NotNull(services, nameof(services));

var serviceProviderFactory = services.GetSingletonInstanceOrNull<IServiceProviderFactory<TContainerBuilder>>();
if (serviceProviderFactory == null)
{
throw new AbpException($"Could not find {typeof(IServiceProviderFactory<TContainerBuilder>).FullName} in {services}.");
}

var builder = serviceProviderFactory.CreateBuilder(services);
builderAction?.Invoke(builder);
return serviceProviderFactory.CreateServiceProvider(builder);
}

2.3 初始化 Abp 框架

這里針對?IApplicationBuilder?的擴展是在模塊包?Volo.Abp.AspNetCore 當中的,這里僅講解 ASP.NET Core Mvc 項目是如何處理的。

public static void InitializeApplication([NotNull] this IApplicationBuilder app)
{
Check.NotNull(app, nameof(app));


app.ApplicationServices.GetRequiredService<ObjectAccessor<IApplicationBuilder>>().Value = app;


app.ApplicationServices.GetRequiredService<IAbpApplicationWithExternalServiceProvider>().Initialize(app.ApplicationServices);
}

這里可能會疑惑?ObjectAccessor<IApplicationBuilder>?是在什么時候注入的,其實該類型是在?AbpAspNetCoreModule 模塊注冊的。

public class AbpAspNetCoreModule : AbpModule
{

public override void ConfigureServices(ServiceConfigurationContext context)
{

context.Services.AddObjectAccessor<IApplicationBuilder>();
}

}

接著看初始化方法內(nèi)部的操作,初始化方法定義是在基類當中,方法名是?InitializeModules()?,在方法內(nèi)部,通過?IModuleManager 來執(zhí)行模塊的初始化方法。

protected virtual void InitializeModules()
{
using (var scope = ServiceProvider.CreateScope())
{
scope.ServiceProvider
.GetRequiredService<IModuleManager>()
.InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider));
}
}

除了模塊的初始化,模塊的銷毀動作 Abp vNext 好像是沒有作處理,你可以掛載?IApplicationLifetime.ApplicationStopping 事件來手動執(zhí)行模塊的銷毀方法。

三、總結(jié)

總體來說 Abp vNext 的啟動流程與之前精簡了許多,這是因為在新的框架當中將許多基礎(chǔ)組件從核心層移除了,用戶可以自由選擇自己需要加載的組件。IoC 相關(guān)的代碼則是通過的 Microsoft Dependency 提供的 IServiceProvider/IServiceCollection?進行操作,沒有了之前的?IocManager。

原文地址:https://www.cnblogs.com/myzony/p/10722480.html

.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?

總結(jié)

以上是生活随笔為你收集整理的[Abp vNext 源码分析] - 1. 框架启动流程分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。