.NET Core 开发实战
  • 目录
  • 第1课:课程介绍
  • 第2课:内容综述
  • 第3课:.NET Core的现状、未来以及环境搭建
  • 第4课:Startup:掌握ASP.NET Core的启动过程
  • 第5课:依赖注入:良好架构的起点
  • 第6课:作用域与对象释放行为
  • 第7课:用Autofac增强容器能力
  • 第8课:配置框架:让服务无缝适应各种环境
  • 第9课:命令行配置提供程序
  • 第10课:环境变量配置提供程序
  • 第11课:文件配置提供程序
  • 第12课:配置变更监听
  • 第13课:配置绑定:使用强类型对象承载配置数据
  • 第14课:自定义配置数据源:低成本实现定制化配置方案
  • 第15课:选项框架:服务组件集成配置的最佳实践
  • 第16课:选项数据热更新:让服务感知配置的变化
  • 第17课:为选项数据添加验证:避免错误配置的应用接收用户流量
  • 第18课:日志框架:聊聊记日志的最佳姿势
  • 第19课:日志作用域:解决不同请求之间的日志干扰
  • 第20课:结构化日志组件Serilog:记录对查询分析友好的日志
  • 第21课:中间件:掌控请求处理过程的关键
  • 第22课:异常处理中间件:区分真异常与逻辑异常
  • 第23课:静态文件中间件:前后端分离开发合并部署骚操作
  • 第24课:文件提供程序:让你可以将文件放在任何地方
  • 第25课:路由与终结点:如何规划好你的Web API
  • 第26课:工程结构概览:定义应用分层及依赖关系
  • 第27课:定义Entity:区分领域模型的内在逻辑和外在行为
  • 第28课:工作单元模式(UnitOfWork):管理好你的事务
  • 第29课:定义仓储:使用EF Core实现仓储层
  • 第30课:领域事件:提升业务内聚,实现模块解耦
  • 第31课:APIController:定义API的最佳实践
  • 第32课:集成事件:解决跨微服务的最终一致性
  • 第33课:集成事件:使用RabbitMQ来实现EventBus
  • 第34课:MediatR:轻松实现命令查询职责分离模式(CQRS)
  • 第35课:MediatR:让领域事件处理更加优雅
Powered by GitBook
On this page

第4课:Startup:掌握ASP.NET Core的启动过程

学习分享 丨作者 / 郑 子 铭 丨公众号 / DotNet NB / CloudNative NB

新建一个 ASP.NET Core Web 应用程序

选择 API

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 方法返回了一个 IHostBuilder

它是应用程序启动的核心接口

IHostBuilder 接口有六个方法:

主要关注以下三个:

  • ConfigureAppConfiguration

  • ConfigureHostConfiguration

  • ConfigureServices

接下来,我们添加一些代码演示整个应用程序的启动过程:

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 Startup(IConfiguration configuration)
{
    Console.WriteLine("Startup");
    ...
    
public void ConfigureServices(IServiceCollection services)
{
    Console.WriteLine("ConfigureServices");
    ...
    
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    Console.WriteLine("Configure");
    ...

启动程序查看输出:

ConfigureWebHostDefaults
ConfigureHostConfiguration
ConfigureAppConfiguration
ConfigureServices
Startup
Startup.ConfigureServices
Startup.Configure

调整一下委托的注册顺序

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

本质上,如果查看源码会发现,委托注册进去之后,实际上是按照一定的顺序来执行的:

1、ConfigureWebHostDefaults

这个阶段注册了应用程序必要的几个组件,比如配置的组件、容器组件

2、ConfigureHostConfiguration

用于配置应用程序启动时必要的配置,比如应用程序启动时所需要监听的端口,URL 地址

在这个过程可以嵌入一些自己配置的内容,注入到配置的框架中

3、ConfigureAppConfiguration

用于嵌入自己的配置文件,供应用程序读取,这些配置将会在后续的应用程序执行过程中间每个组件读取

4、ConfigureServices, ConfigureLogging, Startup, Startup.ConfigureServices

用于往容器里注入应用的组件

5、Startup.Configure

用于注入中间件,处理 HttpContext 整个请求过程

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    Console.WriteLine("Startup.Configure");
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseFileServer();

    app.UseWebSockets();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

在整个启动的过程中,Startup 这个类不是必要的,只是让代码结构更加合理

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            Console.WriteLine("ConfigureWebHostDefaults");
            //webBuilder.UseStartup<Startup>();

            webBuilder.ConfigureServices(services =>
            {
                Console.WriteLine("webBuilder.ConfigureServices");
                services.AddControllers();
            });

            webBuilder.Configure(app =>
            {
                Console.WriteLine("webBuilder.Configure");

                app.UseHttpsRedirection();

                app.UseRouting();

                app.UseAuthorization();

                app.UseFileServer();

                app.UseWebSockets();

                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

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddAuthentication();
    services.AddAuthorization();
    Console.WriteLine("Startup.ConfigureServices");
    services.AddControllers();
}

中间件的注册一般放在 Startup 的 Configure

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    Console.WriteLine("Startup.Configure");
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseFileServer();

    app.UseWebSockets();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

GitHub源码链接:

Previous第3课:.NET Core的现状、未来以及环境搭建Next第5课:依赖注入:良好架构的起点

Last updated 3 years ago

https://github.com/MingsonZheng/DotNetCoreDevelopmentActualCombat/tree/main/StartupDemo