.NET8 WebApplication剖析
? WebApplication 是用于配置HTTP管道和路由的web應用程序,接來下我將一一拆解它的組成。
/// <summary>
/// The web application used to configure the HTTP pipeline, and routes.
/// </summary>
[DebuggerDisplay("{DebuggerToString(),nq}")]
[DebuggerTypeProxy(typeof (WebApplication.WebApplicationDebugView))]
public sealed class WebApplication : IHost,IDisposable,IApplicationBuilder,IEndpointRouteBuilder,IAsyncDisposable
IHost
? 首先Web應用是一個程序,而 IHost 就是程序的抽象
public interface IHost : IDisposable
{
IServiceProvider Services { get; }
Task StartAsync(CancellationToken cancellationToken = default (CancellationToken));
Task StopAsync(CancellationToken cancellationToken = default (CancellationToken));
}
? 一個程序具備啟動、停止生命周期,這很好理解。我要說的是 IServiceProvider ,他非常關鍵,后面會在依賴注入章節來詳細解釋。目前你只需要知道他是一個服務供應商就可以了,就可以通過他獲取想要的服務,但前提是你在IOC容器中注冊過。
? Host StartAsync 代碼流如下:
await host._hostLifetime.WaitForStartAsync(token1).ConfigureAwait(false); // 注冊start程序
host.Services.GetService<IStartupValidator>()?.Validate(); // 校驗
IHostedLifecycleService.StartingAsync
IHostedService.StartAsync
IHostedLifecycleService.StartedAsync
host._applicationLifetime.NotifyStarted();
? StopAsync 類似,代碼流如下:
IHostedLifecycleService.StoppingAsync
IHostedService.StopAsync
IHostedLifecycleService.StoppedAsync
this._logger.StoppedWithException((Exception) ex);
? 值得注意的是 IStartupValidator、IHostedService、IHostedLifecycleService 分別為我們提供不同的鉤子,只需要向容器注冊即可加入我們自定義的業務邏輯。
IApplicationBuilder
? WebApplication 實現 IApplicationBuilder 具有pipeline機制。
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
RequestDelegate Build();
? 這里要解釋一下pipeline,管道是.NET中非常普及的一個概念,內核是切面編程,同樣的在后續我們會有專門的章節來例舉它。現在你只需要知道,他是一個洋蔥模型。
? 同時,IApplicationBuilder 從命名上就表達了這是一個構建者模式,因此 WebApplication 提供了 Build
public WebApplication Build()
{
this._hostApplicationBuilder.Services.Add(this._genericWebHostServiceDescriptor);
this.Host.ApplyServiceProviderFactory(this._hostApplicationBuilder);
this._builtApplication = new WebApplication(this._hostApplicationBuilder.Build());
return this._builtApplication;
}
? 篇幅問題這里不展開討論,但在Build方法中會有四個鉤子被執行
public IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate)
public IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate)
public IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
public IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate)
? 最終服務容器會被標記成只讀
IEndpointRouteBuilder
? IEndpointRouteBuilder為程序定義路由構建的約定。
ICollection<EndpointDataSource> DataSources { get; }
? 這是 WebApplication 中的實現,可以看到 EndpointDataSource 的實現會被組合進來。
public IReadOnlyList<Endpoint> Endpoints
{
get
{
EndpointDataSource requiredService = this._webApplication.Services.GetRequiredService<EndpointDataSource>();
return requiredService is CompositeEndpointDataSource endpointDataSource && endpointDataSource.DataSources.Intersect<EndpointDataSource>((IEnumerable<EndpointDataSource>) this._webApplication.DataSources).Count<EndpointDataSource>() != this._webApplication.DataSources.Count ? new CompositeEndpointDataSource((IEnumerable<EndpointDataSource>) this._webApplication.DataSources).Endpoints : requiredService.Endpoints;
}
}
? EndpointDataSource實際上就是一組 Endpoint,而 Endpoint 是 AspNetCore 下極其重要的一節,同樣會在后續展開講。現在你只需要知道,它表示一個處理 HTTP 請求的終點,包含了處理請求的邏輯和相關的元數據。
IAsyncDisposable
? IAsyncDisposable 是 .NET Core 2.0 引入的一個接口,用于異步釋放資源的模式。它是 IDisposable 接口的異步版本。某些資源的釋放可能涉及到異步操作,使用 IDisposable 接口的同步釋放模式可能會導致阻塞線程,影響應用程序的性能和響應性。
public interface IAsyncDisposable
{
ValueTask DisposeAsync();
}
? 在使用完該對象后,可以使用 await using語法糖或直接調用 ``DisposeAsync()` 方法來釋放資源。
Run
? Run 函數是 WebApplication 的啟動按鈕,你可以傳遞一個url,加入到監聽列表
public void Run([StringSyntax("Uri")] string? url = null)
{
this.Listen(url);
// public static void Run(this IHost host) => host.RunAsync().GetAwaiter().GetResult();
HostingAbstractionsHostExtensions.Run(this);
}
? HostingAbstractionsHostExtensions.Run的源碼相對簡單,host的 StartAsync、WaitForShutdownAsync 在上面都介紹了,WebApplication 的 DisposeAsync 也在finally塊中觸發
public static async Task RunAsync(this IHost host, CancellationToken token = default (CancellationToken))
{
try
{
ConfiguredTaskAwaitable configuredTaskAwaitable = host.StartAsync(token).ConfigureAwait(false);
await configuredTaskAwaitable;
configuredTaskAwaitable = host.WaitForShutdownAsync(token).ConfigureAwait(false);
await configuredTaskAwaitable;
}
finally
{
if (host is IAsyncDisposable asyncDisposable)
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
else
host.Dispose();
}
}
? 上面有個很有意思的點是,為什么要在finally塊中觸發?這是因為Host的生命周期函數都用了聯合取消令牌,這是一種安全取消協作模式,在令牌取消后會觸發一個 OperationCanceledException 異常,進而在這種情況下還能夠正常處理銷毀工作,這是一種非常優秀的編程習慣。
總結
以上是生活随笔為你收集整理的.NET8 WebApplication剖析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手撕Vuex-模块化共享数据上
- 下一篇: 【scipy 基础】--积分和微分方程