前言

一个Asp.NetCore项目,知道大概的启动流程是有必要的,比如后续遇见配置信息覆盖等相关问题时也大概知道是什么原因,了解原因之后,再去搜索引擎找答案,否则目标不明确,茫茫人海怎么会一下找到自己想要的,除非是“偶遇”;“偶遇”太难,一起浅析一个Asp.NetCore 项目的启动流程;

正文

先创建一个WebAPI项目,用的是.NetCore3.1,后续的项目例子都统一用.NetCore3.1,除非特殊说明;项目如下:

如上图所示,一个WebAPI项目启动方式本质也是一个控制台程序,程序入口都是从Main函数开始,就从里面方法看看大概都做了什么,其中择取几个方法源码简要说明主要功能,通过增加代码注释的方式(我觉得这样比较方便对应浏览),完整源代码从以下两个地址获取,通过Everything查找工具比较方便查询代码:

主项目地址:https://github.com/dotnet/aspnetcore/tree/v3.1.0

扩展项目地址:https://github.com/dotnet/extensions/releases/tag/v3.1.6

GitHub代码地址

1. Host.CreateDefaultBuilder方法

public static IHostBuilder CreateDefaultBuilder(string[] args)
{//实例化一个HostBuildervar builder = new HostBuilder();//设置根目录builder.UseContentRoot(Directory.GetCurrentDirectory());//设置 Host相关配置的配置源builder.ConfigureHostConfiguration(config =>{//从环境变量中获取,前缀名为DOTNET_config.AddEnvironmentVariables(prefix: "DOTNET_");//如果命令行中有参数,可从命令行中读取if (args != null){config.AddCommandLine(args);}});//设置应用程序配置的配置源builder.ConfigureAppConfiguration((hostingContext, config) =>{var env = hostingContext.HostingEnvironment;//根据运行环境加载不同的配置文件,并开启了热更新config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName)){var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));if (appAssembly != null){config.AddUserSecrets(appAssembly, optional: true);}}//可从环境变量中获取config.AddEnvironmentVariables();//如果命令行中有参数,可从命令行中读取if (args != null){config.AddCommandLine(args);}})//配置日志显示.ConfigureLogging((hostingContext, logging) =>{//判断操作系统var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);//如果是Windows系统,配置对应的显示级别//IMPORTANT: This needs to be added *before* configuration is loaded, this lets//the defaults be overridden by the configuration.if (isWindows){// Default the EventLogLoggerProvider to warning or abovelogging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);}//获取配置文件中Logging 段相关的配置信息添加到日志配置中logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));//在控制台输出,所以启动程序的时候就看见输出日志logging.AddConsole();//在Debug窗口输出logging.AddDebug();logging.AddEventSourceLogger();//如果是Windows系统,可以在系统日志中输出日志if (isWindows){// Add the EventLogLoggerProvider on windows machineslogging.AddEventLog();}})//使用默认的依赖注入容器.UseDefaultServiceProvider((context, options) =>{var isDevelopment = context.HostingEnvironment.IsDevelopment();options.ValidateScopes = isDevelopment;options.ValidateOnBuild = isDevelopment;});return builder;
}

2. ConfigureWebHostDefaults 方法

public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure)
{return builder.ConfigureWebHost(webHostBuilder =>{//指定是用的服务器及集成一些默认管道WebHost.ConfigureWebDefaults(webHostBuilder);//调用传入的委托,这里是外部指定Startup类做服务注册和管道配置configure(webHostBuilder);});
}

2.1  WebHost.ConfigureWebDefaults方法

internal static void ConfigureWebDefaults(IWebHostBuilder builder)
{builder.ConfigureAppConfiguration((ctx, cb) =>{if (ctx.HostingEnvironment.IsDevelopment()){//静态文件环境的配置启用StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);}});//指定Kestrel作为默认的Web服务器builder.UseKestrel((builderContext, options) =>{options.Configure(builderContext.Configuration.GetSection("Kestrel"));})// 服务中间的注册,包含路的中间件注册.ConfigureServices((hostingContext, services) =>{// 针对配置节点AllowedHosts改变时的回调// Fallbackservices.PostConfigure<HostFilteringOptions>(options =>{if (options.AllowedHosts == null || options.AllowedHosts.Count == 0){// "AllowedHosts": "localhost;127.0.0.1;[::1]"var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);// Fall back to "*" to disable.options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });}});//对应配置改变时触发通知// Change notificationservices.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase)){services.Configure<ForwardedHeadersOptions>(options =>{options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;// Only loopback proxies are allowed by default. Clear that restriction because forwarders are// being enabled by explicit configuration.options.KnownNetworks.Clear();options.KnownProxies.Clear();});services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();}services.AddRouting();})//对使用IIS相关中间件.UseIIS().UseIISIntegration();
}

3. Build方法,其实这个方法就是根据之前配置构造出一个IHost对象

public IHost Build()
{if (_hostBuilt){throw new InvalidOperationException("Build can only be called once.");}_hostBuilt = true;//执行ConfigureHostConfiguration添加的一系列配置回调方法BuildHostConfiguration();//运行环境相关创建,如ApplicationName、EnvironmentName、ContentRootPath等CreateHostingEnvironment();//构建HostBuilderCreateHostBuilderContext();//执行ConfigureAppConfigureation添加的一系列配置回调方法BuildAppConfiguration();//注入默认服务如:IHost、ILogging等,执行ConfigureServices添加的一系列回调方法CreateServiceProvider();return _appServices.GetRequiredService<IHost>();
}

4. Run()方法,开启服务器,之后就可以进行请求了

综上几个关键方法,从其中Host这个关键词出现很多次,其实在Asp.Net Core应用中是通过配置并启动一个Host来完成应用程序的启动和生命周期的管理。而Host主要就是对Web Server的配置和请求处理管理的管理,简要流程如下图:

在整个启动流程中,返回的IHostBuilder中暴露配置和注入的相关接口,可用于自己定义扩展,接下来通过打印的方式来看看一下几个暴露方法的执行顺序,其实以上Build方法的时候已经明确了对应方法的顺序;

改造代码如下:

Startup方法中的三个方法也增加对应的打印,运行如下:

如上图,除了Startup中的ConfigureServices会跟随ConfigureWebHostDefaults改变以外,其他方法顺序都是固定。那这些方法主要作用都是什么呢?如下图:

图中Program.ConfigureServices和Startup.ConfigureServices的执行顺序会根据ConfigureWebHostDefaults的位置改变会交替变动;

总结

以上内容只是提取了其中比较关键的流程进行说明,并没有详细解析源代码,这里只是先浅析,后续再继续一起深究源代码;下一节说说依赖注入;

跟我一起学.NetCore之Asp.NetCore启动流程浅析相关推荐

  1. 跟我一起学.NetCore之Asp.NetCore中集成Autofac扩展

    前言 前两节针对.NetCore自带的依赖注入进行简要概述,对于日常开发的需求应该是能满足了,那为什么还需要引入第三方依赖注入组件呢,这里就从自带的依赖注入来分析,有什么样的需求满足不了?主要归纳为以 ...

  2. ASP.NETCore学习记录(一)

    ASP.NETCore学习记录(一) asp.net core介绍  Startup.cs  ConfigureServices  Configure  0. ASP.NETCore 介绍 ASP.N ...

  3. ASP.NETCore

    0. ASP.NETCore 介绍 ASP.NETCore是一个新的开源和跨平台的框架,用于构建如Web应用.物联网(IoT)应用和移动后端应用等连接到互联网的基于云的现代应用程序.ASP.NET C ...

  4. Asp.NetCore轻松学-部署到 IIS 进行托管

    前言 经过一段时间的学习,终于来到了部署服务这个环节,.NetCore 的部署方式非常的灵活多样,但是其万变不离其宗,所有的 Asp.NetCore 程序都基于端口的侦听,在部署的时候仅需要配置侦听地 ...

  5. ASP.netcore MVC钉钉H5微应用(一)准备工作

    本文是我在做ASP.netcore MVC钉钉H5微应用的第一章,准备工作 首先,进入钉钉开发平台,需要自己在钉钉上创建一个工作室,然后申请成为开发者,并创建一个H5微应用 在H5微应用里填写需要的信 ...

  6. Asp.NetCore MVC Web 应用

    Asp.NetCore MVC 与 普通的MVC 基本一致, 只是代码结构稍有改动 一.创建项目 1. 2. 3. 项目结构 二. 构建数据模型 1. Startup类中配置EF Core MySql ...

  7. ASP.NETCore微服务(七)——【docker部署linux上线】(ECS+linux+docker+API上线部分)

    ASP.NETCore微服务(七)--[docker部署linux上线](ECS+linux+docker+API上线部分) 对应练习sql下载路径(0积分):[ASP.NETCore微服务(一)-- ...

  8. 4 angular 重构 项目_c# – 将Angular 4添加到ASP.NETCore项目中

    我想在Visual Studio 2017中的ASP.NetCore 1.1项目中使用Angular 4(读作:* .csproj文件) 以前使用ASP.NET Core 1.0和Visual Stu ...

  9. 极简实用的Asp.NetCore模块化框架决定免费开源了

    背景 在开发这个框架之前,前前后后看过好几款模块化的框架,最后在一段时间内对ABP VNext痛下狠心,研究一段时间后,不得不说 ABP VNext的代码层面很规范,也都是一些最佳实践,开发出一个模块 ...

最新文章

  1. AIX5.3安装bash shell
  2. Ubuntu14.04 工作区设置
  3. 12、Kubernetes核心技术Ingress
  4. JavaScript中实现私有属性的写类方式(2)
  5. openstack rootwrap详解
  6. PHP对请求时间范围条件的判断
  7. 【浸入式英文学习方式】山姆莱萌帮助孩子建立扎实语言功底
  8. Linux搭建虚拟机,桥接模式下,主机能够Ping通虚拟机,虚拟机ping不通主机
  9. 模块说和神经网络学说_教师招聘中常见的5种脑机能学说
  10. RocketMQ入门
  11. Python机器学习---2.聚类分析代码部分
  12. 修改Maven本地仓库的位置 方法
  13. ufw禁止IP访问ubuntu服务器
  14. .Net 的 Web 项目中 关于TreeView 的 checkBox 的操作……
  15. 【14年浙江省赛 ZOJ 3780】Paint the Grid Again【图转换】
  16. 游戏技能一:激光扫射的实现【CocosCreator 2D】【TypeScript】
  17. C语言提取PDF字符串,C语言资料精华.pdf
  18. 产品经理如何设计网页导航菜单
  19. 超酷的iOS动画集合
  20. Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?

热门文章

  1. VMware虚拟机VMware Authorization Service不能启动问题
  2. modernizer的意义
  3. iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序
  4. SQL Server创建索引(转)
  5. 开源项目导入eclipse的一般步骤[转]
  6. Oracle命令--alter 操作
  7. 个人电脑的楷模:新款IMac G5
  8. linux是只读添加 来覆盖,Linux之指令 重定向 文件覆盖和文件追加
  9. php larval开发规范,数据模型 |《 Laravel 项目开发规范 5.5》| Laravel China 社区
  10. windows 系统监视器_使用Windows 7中的可靠性监视器对计算机问题进行故障排除