Asp.net Core的設計和主要對象
WebHostBuilder:它的責任可以使用哪個監聽服務器,使用委托注冊中間件,最重要是Webhost
IWebHostBuilder UseServer(IServer server); IWebHostBuilder Configure(Action<IApplicationBuilder> configure); WebHost Build();
HttpContext:面向傳輸層的服務器負責請求的監聽、接收和最終的響應,當它接收到客戶端發送的請求后,需要將它分發給后續中間件進行處理,請求在服務器與中間件之間,以及在中間件之間的分發是通過共享上下文的方式實現的,要屏蔽底層Server細節
RequestDelegate:既然針對當前請求的所有輸入和輸出都通過HttpContext來表示,那么HttpHandler就可以表示成一個Action<HttpContext>對象
MiddleWare:Func<RequestDelegate, RequestDelegate>對象,也就是說它的輸入和輸出都是一個RequestDelegate
ApplicationBuilder:Use方法用來注冊提供的中間件,Build方法則將注冊的中間件構建成一個RequestDelegate對象。IApplicationBuilder:主要規格有Use注冊RequestDelegate,創建(Build)RequestDelegate,另外還有ApplicationServices(IServiceProvider)、Properties、IFeatureCollection
Server與WebHost的責任將如何划分呢?
WebHost是啟動服務器,有個run方法或Start方法,啟動是Server,控制權轉讓
Server的職責:有個啟動方法,里面有個while(true){ }方法,如eventloop
服務器會綁定到指定的端口進行請求監聽,一旦有請求抵達,服務器會根據該請求創建出代表上下文的HttpContext對象,並將該上下文作為輸入調用由所有注冊中間件構建而成的RequestDelegate對象。
ABP的設計,基於多模塊的設計,AbpModule建立Application基礎
它分兩步做,相互獨立的,它抽象相應的接口,
1、將模塊的列表遍歷注冊服務到容器,分三個階段PreConfigureServices(預注冊)、ConfigureServices(注冊)、PostConfigureServices(注冊后)。
2,應用的初始化,即將設置服務提供方ServiceProvider,並執行四個生命周期函數,OnPreApplicationInitialization,OnApplicationInitialization、OnPostApplicationInitialization、OnApplicationShutdown
詳細:
1、利用AbpApplicationFactory.Create方法,創建一個AbpApplication,它的創建,構建函數就包括填充模塊列表、執行第一步服務注冊的操作。
2、應用初始化,解決兩個問題,服務的提供方ServiceProvider使用是默認的,還是第三方的。其它是執行應用邏輯,即應用的初始化,而應用種類又分為兩種,一種是IAbpApplicationWithInternalServiceProvider,另一種是IAbpApplicationWithExternalServiceProvider
第一種,典例是控制台應用,
public void Initialize() { ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope(); SetServiceProvider(ServiceScope.ServiceProvider); InitializeModules(); }
第二種,ASP.net Core利用IApplicationBuilder以及下面的ApplicationServices
public void Initialize(IServiceProvider serviceProvider) { Check.NotNull(serviceProvider, nameof(serviceProvider)); SetServiceProvider(serviceProvider); InitializeModules(); }
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); }
Asp.net Core應用
Startup模塊負責將各模塊內服務注冊,定義管道。剛好對應的AbpApplication兩步做
注冊服務:即創建一個AbpApplication,基於ISerivceCollection剛好定義拓展方法AddApplication
AddApplication方法就是生成應用的實例
AbpApplication職責:abpModule的模塊的容器,它包含模塊的列表,服務的容器,提供服務,優雅到關閉服務和模塊
ConfigureServices最重要的是將模塊的服務注冊到ServiceCollection里面,為啟動服務初始化作准備。
(ConfigureServices(IServiceCollection services),它遍歷的Abp模塊(注意,模塊的依賴關系影響調用的順序),調用模塊的三個生命周期方法。PreConfigureServices、ConfigureServices、PostConfigureServices。
注冊管道Configure(IApplicationBuilder):即第二步,即執行模塊內應用始化操作,擴展一個InitializeApplication方法進行集成,它的主要功能:
1)設置SetServiceProvider,使用的是AbpAutofacServiceProviderFactory
2)遍歷模塊的應用生命周期函數。(Startup模塊主要配置管道)
Asp.net Core下的Startup模塊的ConfigureServices的方法,
public class Startup
{
public void ConfigureServices(IServiceCollection services) { services.AddApplication<AbpModule>(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.InitializeApplication(); } }
3、相關知識點
AbpApplication里的是模塊的列表,每個模塊又有它的依賴,形成是一個樹狀的結果,根節點是啟動的 AppModule
IAbpModuleDescriptor定義,嵌套,服務配置的上下文的內容
public interface IAbpModuleDescriptor { Type Type { get; } Assembly Assembly { get; } IAbpModule Instance { get; } bool IsLoadedAsPlugIn { get; } IReadOnlyList<IAbpModuleDescriptor> Dependencies { get; } }
Abp模塊的定義,主要是對應用服務生命狀態的描述。
public abstract class AbpModule :
IAbpModule,
IOnPreApplicationInitialization,
IOnApplicationInitialization,
IOnPostApplicationInitialization,
IOnApplicationShutdown,
IPreConfigureServices,
IPostConfigureServices
public interface IAbpModule { void ConfigureServices(ServiceConfigurationContext context); }
如何使用第三方提供服務
public static void UseAutofac(this AbpApplicationCreationOptions options) { var builder = new ContainerBuilder(); options.Services.AddObjectAccessor(builder); options.Services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder)); }
public static IHostBuilder UseAutofac(this IHostBuilder hostBuilder) { var containerBuilder = new ContainerBuilder(); return hostBuilder.ConfigureServices((_, services) => { services.AddObjectAccessor(containerBuilder); }) .UseServiceProviderFactory(new AbpAutofacServiceProviderFactory(containerBuilder)); }
AbpApplication主要實現在於抽象類abstract class AbpApplicationBase : IAbpApplication
AddCoreServices方法:注冊ASP.net core的 Option,Logging,Location方法
AddCoreAbpServices方法:將IConfiguration替換,注冊模塊加載,類庫存,類型查找,Volo.Abp.Core模塊的服務,配置模塊4個生命周期方法
services.TryAddSingleton<IModuleLoader>(moduleLoader);
services.TryAddSingleton<IAssemblyFinder>(assemblyFinder); services.TryAddSingleton<ITypeFinder>(typeFinder); services.AddAssemblyOf<IAbpApplication>(); services.Configure<AbpModuleLifecycleOptions>(options => { options.Contributors.Add<OnPreApplicationInitializationModuleLifecycleContributor>(); options.Contributors.Add<OnApplicationInitializationModuleLifecycleContributor>(); options.Contributors.Add<OnPostApplicationInitializationModuleLifecycleContributor>(); options.Contributors.Add<OnApplicationShutdownModuleLifecycleContributor>(); });
IModuleLoader的方法 LoadModules()方法,包括查找模塊,登記模塊,注冊模塊,構建模塊集合,按依賴重新排序,調用模塊生命周期方法,模塊的服務注冊,
// 掃描模塊類型,並構建模塊描述對象集合。
var modules = GetDescriptors(services, startupModuleType, plugInSources);
// 按照模塊的依賴性重新排序。
modules = SortByDependency(modules, startupModuleType); // 調用模塊的三個生命周期方法。 ConfigureServices(modules, services);
ModuleManager管理模塊生命周期方法
順序:
PreConfigureServices、做哪些操作合適,比如rvices.AddConventionalRegistrar
ConfigureServices,主要的服務注冊的地方
PostConfigureServices
{
var context = new ServiceConfigurationContext(services); services.AddSingleton(context); foreach (var module in modules) { if (module.Instance is AbpModule abpModule) { abpModule.ServiceConfigurationContext = context; } } //PreConfigureServices foreach (var module in modules.Where(m => m.Instance is IPreConfigureServices)) { ((IPreConfigureServices)module.Instance).PreConfigureServices(context); } //ConfigureServices foreach (var module in modules) { if (module.Instance is AbpModule abpModule) { if (!abpModule.SkipAutoServiceRegistration) { services.AddAssembly(module.Type.Assembly); } } module.Instance.ConfigureServices(context); } //PostConfigureServices foreach (var module in modules.Where(m => m.Instance is IPostConfigureServices)) { ((IPostConfigureServices)module.Instance).PostConfigureServices(context); } foreach (var module in modules) { if (module.Instance is AbpModule abpModule) { abpModule.ServiceConfigurationContext = null; } } }
一個模塊有 4 個生命周期,它們都是在抽象基類 AbpModule
當中定義的,分別是 預加載、初始化、初始化完成、銷毀。前三個生命周期是依次執行的 預加載->初始化->初始化完成,而最后一個銷毀動作則是在程序終止的時候,通過 AbpModuleManager
遍歷模塊,調用其 ShutDown()
方法進行銷毀動作。
Application初始化 Initialize,
定義一個接口,依賴外部IServiceProvider的AbpApplication。首先設置IServiceProvider,再執行相關模塊化的相關操作
public interface IAbpApplicationWithExternalServiceProvider : IAbpApplication { void Initialize([NotNull] IServiceProvider serviceProvider); }
注意IServiceProvider是誰提供,默認還是 AutoFac提供,AbpApplicationWithExternalServiceProvider是在注冊Server時,UseServiceProviderFactory進行替換
AbpApplicationWithInternalServiceProvider,這里Initialize並沒有傳值ServiceProvider
public void Initialize()
{
ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope(); SetServiceProvider(ServiceScope.ServiceProvider); InitializeModules(); }
BuildServiceProviderFromFactory,查找到IServiceProviderFactory,=》AbpAutofacServiceProviderFactory
創建ContainerBuilder,注冊服務到autofac,返回IServiceProvider,
這里的SetServiceProvider方法,一個是給Application,另一個是容器
protected virtual void SetServiceProvider(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider; ServiceProvider.GetRequiredService<ObjectAccessor<IServiceProvider>>().Value = ServiceProvider; }
InitializeModules使用ModuleManager
public void InitializeModules(ApplicationInitializationContext context)
{
LogListOfModules();
foreach (var Contributor in _lifecycleContributors) { foreach (var module in _moduleContainer.Modules) { Contributor.Initialize(context, module.Instance); } } _logger.LogInformation("Initialized all ABP modules."); }
模塊級別與應用級別的生命周期有什么不同
框架模塊是框架的核心模塊,其模塊的邏輯與處理基本都在傳統的三個生命周期進行處理。在我們的services.AddApplication()
階段就已經完成所有初始化,
可以給 應用程序模塊 提供服務
第二種則是 應用程序模塊,這種模塊則是實現了特定的業務/功能,例如身份管理、租戶管理等,而新增加的四個生命周期基本是為這種類型的模塊服務的。
IOnPreApplicationInitialization
、IOnApplicationInitialization
、IOnPostApplicationInitialization
、IOnApplicationShutdown
2、注冊的規約有哪些,如何自定義,在哪里注入
DefaultConventionalRegistrar
理解ObjectAccessor,添加一個空的對象訪問器,該訪問器的值會在初始化的時候被賦值,例如在上文當中的 IServiceProvider
通過 ObjectAccessor<T>
對象包裹起來,其值是 NULL,但是在后面我們可以根據自己的需要替換其具體的 Value 另外知識點,out,in 協變和逆變
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);