ASP.NET Core 启动过程
- .Net Core 3.1
- VS 2019
创建一个新的ASP.NET Core Web API应用程序
在项目目录中有两个关键类 Program.cs 和 Startup.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
在Program.cs 的Main函数 调用 CreateHostBuilder 这个方法
CreateHostBuilder 返回一个 IHostBuilder
IHostBuilder 是我们应用程序启动的核心接口
public interface IHostBuilder
{
IDictionary<object, object> Properties { get; }
IHost Build();
IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate);
IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate);
IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate);
IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory);
}
这个接口主要有以上6个方法
我们需要关注的是:
- ConfigureAppConfiguration
- ConfigureHostConfiguration
- ConfigureServices
这三个方法
通过修改Program 和 Startup 来演示启动过程
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder => {
Console.WriteLine("ConfigureAppConfiguration");
})
.ConfigureServices(service => {
Console.WriteLine("ConfigureServices");
})
.ConfigureHostConfiguration(builder => {
Console.WriteLine("ConfigureHostConfiguration");
})
.ConfigureWebHostDefaults(webBuilder =>
{
Console.WriteLine("ConfigureWebHostDefaults");
webBuilder.UseStartup<Startup>();
});
修改Startup类
public class Startup
{
public Startup(IConfiguration configuration)
{
Console.WriteLine("Startup");
// snip
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
Console.WriteLine("Startup.ConfigureServices");
// snip
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Console.WriteLine("Startup.Configure");
// snip
}
}
查看输出结果
ConfigureWebHostDefaults
ConfigureHostConfiguration
ConfigureAppConfiguration
ConfigureServices
Startup
Startup.ConfigureServices
Startup.Configure
接下来调整一下CreateHostBuilder 中注册顺序
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
Console.WriteLine("ConfigureWebHostDefaults");
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(service => {
Console.WriteLine("ConfigureServices");
})
.ConfigureAppConfiguration(builder => {
Console.WriteLine("ConfigureAppConfiguration");
})
.ConfigureHostConfiguration(builder => {
Console.WriteLine("ConfigureHostConfiguration");
});
然后重新执行查看结果
ConfigureWebHostDefaults
ConfigureHostConfiguration
ConfigureAppConfiguration
Startup
Startup.ConfigureServices
ConfigureServices
Startup.Configure
发现两次执行的结构有所不同,这个和委托注册进去的顺序有关系,实际上是按照一定的顺序执行的;
整个启动过程分5个阶段:
- ConfigureWebHostDefaults: 这个阶段注册了我们应用程序必要的几个组件,比如配置的组件,容器的组件
- ConfigureHostConfiguration:是用来配置我们应用程序启动时必要的配置,比如应用程序启动时需要监听的端口,URL地址等,在这个过程可以嵌入一些自己配置的类容,注入到配置的框架中
- ConfigureAppConfiguration:用于嵌入自己的配置文件供应用程序读取,这些配置将会在后续的应用程序执行过程中间每个组件读取
- ConfigureServices, ConfigureLogging, Startup, Startup.ConfigureServices:都是用来往容器里面注入我们的应用组件
- Startup.Configure:用来注入中间件,处理 HttpContext 整个请求过程
在整个启动过程中,Startup 这个类不是必要的.只是这样让代码结构更加合理
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
Console.WriteLine("ConfigureWebHostDefaults");
webBuilder.ConfigureServices(services =>
{
Console.WriteLine("webBuilder.ConfigureServices");
services.AddControllers();
});
webBuilder.Configure(app => {
Console.WriteLine("webBuilder.Configure");
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
});
})
.ConfigureServices(service => {
Console.WriteLine("ConfigureServices");
})
.ConfigureAppConfiguration(builder => {
Console.WriteLine("ConfigureAppConfiguration");
})
.ConfigureHostConfiguration(builder => {
Console.WriteLine("ConfigureHostConfiguration");
});
运行得到的结果
ConfigureWebHostDefaults
ConfigureHostConfiguration
ConfigureAppConfiguration
webBuilder.ConfigureServices
ConfigureServices
webBuilder.Configure
与之前执行的顺序也是一致的.
服务注册一般放在 Startup 的 ConfigureServices,一般是services.AddXXX
中间件的注册一般放在 Startup 的 Configure 一般是 app.UseXXX