【.Net Core】.Net Core 源码分析与深入理解 - 配置中心 Startup.cs (二)
源码版本: .Net Core 3.1.14
上篇文章: 【.Net Core】.Net Core 源码分析与深入理解 - 入口 Program.cs (一)
注意:本篇文章主要研究的是 Startup.cs 中做了什么,Configure里面是怎么配置管道的,各种参数到底有何功能。
具体Configure的源码探究比较复杂,准备再仔细学习一下,等下一章 【.Net Core】.Net Core 源码分析与深入理解 - 管道核心 Configure(三)。
可以看到Startup.cs 的代码如下,接下来将会从执行顺序逐一分析。
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
IConfiguration:应用程序的各种配置信息。
IApplicationBuilder:获取应用程序中的环境变量,配置Http请求管道。
IHostingEnvironment:包含应用程序宿主环境相关信息的接口。
Startup Constructor 构造函数
首先是构造函数注入进来的Configuration对像,这个对象的加载进了不同类型的配置信息,通过统一的抽象接口进行管理。比如说可以在appsettings.json中配置数据库连接信息,在这里使用配置好的信息。
IConfiguration的源码如下,地址 ......\extensions-3.1.14\src\Configuration\Config.Abstractions\src\IConfiguration
/// <summary>
/// Represents a set of key/value application configuration properties.
/// </summary>
public interface IConfiguration
{
/// <summary>
/// Gets or sets a configuration value.
/// </summary>
/// <param name="key">The configuration key.</param>
/// <returns>The configuration value.</returns>
string this[string key] { get; set; } /// <summary>
/// Gets a configuration sub-section with the specified key.
/// </summary>
/// <param name="key">The key of the configuration section.</param>
/// <returns>The <see cref="IConfigurationSection"/>.</returns>
/// <remarks>
/// This method will never return <c>null</c>. If no matching sub-section is found with the specified key,
/// an empty <see cref="IConfigurationSection"/> will be returned.
/// </remarks>
IConfigurationSection GetSection(string key); /// <summary>
/// Gets the immediate descendant configuration sub-sections.
/// </summary>
/// <returns>The configuration sub-sections.</returns>
IEnumerable<IConfigurationSection> GetChildren(); /// <summary>
/// Returns a <see cref="IChangeToken"/> that can be used to observe when this configuration is reloaded.
/// </summary>
/// <returns>A <see cref="IChangeToken"/>.</returns>
IChangeToken GetReloadToken();
}
它有以下三个方法:
- GetChildren():获取直接子配置子节
- GetReloadToken():返回一个IChangeToken,可用于确定何时重新加载配置
- GetSection(String):获取指定键的子节点
ConfigureServices
接下来主要说一下方法里面配置的是什么,重点在于参数是什么,怎么来的,这个方法的参数是IServiceCollection,是一个非常重要的对象,这是一个原生的Ioc容器,所有需要用到的服务都可以注册到里面, 调用service.AddXXXX方法,比如数据库、MVC、跨域、swagger、过滤器等Middleware。
这个IServiceCollection 接口,在框架初始建立时,看起来只有 services.AddControllers(); 注册了控制器的服务,其实不然,基本上要用到的服务全都注册在里面。这里如果直接去看IServiceCollection的接口是看不出什么的,这个需要回到入口--Program。
当IHost对象建立后,第二步Build时,执行了以下方法(源码位置......\extensions-3.1.14\src\Hosting\Hosting\src\HostBuilder ):
public IHost Build()
{
if (_hostBuilt)
{
throw new InvalidOperationException("Build can only be called once.");
}
_hostBuilt = true; BuildHostConfiguration(); // 创建ConfigurationBuilder,并调用_configureHostConfigActions列表进行配置的初始化
CreateHostingEnvironment(); // 构建HostingEnvironment对象,从配置中获取key为applicationName、environment的应用名称和环境名称
CreateHostBuilderContext(); // HostBuilderContext宿主上下文,保存HostingEnvironment、Configuration和宿主的一些自定义属性
BuildAppConfiguration(); // 合并之前的_hostConfiguration,调用_configureAppConfigActions列表初始化应用配置
CreateServiceProvider(); return _appServices.GetRequiredService<IHost>();
}
可以看到主要执行了5个方法,但是重要的是最后一个方法 CreateServiceProvider()。
private void CreateServiceProvider()
{
var services = new ServiceCollection();
#pragma warning disable CS0618 // Type or member is obsolete
services.AddSingleton<IHostingEnvironment>(_hostingEnvironment);
#pragma warning restore CS0618 // Type or member is obsolete
services.AddSingleton<IHostEnvironment>(_hostingEnvironment);
services.AddSingleton(_hostBuilderContext);
// register configuration as factory to make it dispose with the service provider
services.AddSingleton(_ => _appConfiguration);
#pragma warning disable CS0618 // Type or member is obsolete
services.AddSingleton<IApplicationLifetime>(s => (IApplicationLifetime)s.GetService<IHostApplicationLifetime>());
#pragma warning restore CS0618 // Type or member is obsolete
services.AddSingleton<IHostApplicationLifetime, ApplicationLifetime>();
services.AddSingleton<IHostLifetime, ConsoleLifetime>();
services.AddSingleton<IHost, Internal.Host>();
services.AddOptions();
services.AddLogging(); foreach (var configureServicesAction in _configureServicesActions)
{
configureServicesAction(_hostBuilderContext, services);
} var containerBuilder = _serviceProviderFactory.CreateBuilder(services); foreach (var containerAction in _configureContainerActions)
{
containerAction.ConfigureContainer(_hostBuilderContext, containerBuilder);
} _appServices = _serviceProviderFactory.CreateServiceProvider(containerBuilder); if (_appServices == null)
{
throw new InvalidOperationException($"The IServiceProviderFactory returned a null IServiceProvider.");
} // resolve configuration explicitly once to mark it as resolved within the
// service provider, ensuring it will be properly disposed with the provider
_ = _appServices.GetService<IConfiguration>();
}
从第一句,var services = new ServiceCollection();,可以看出来了,我们在Startup.cs中的 IServiceCollection 服务容器是这里创建并初始化的。
接下来都是注册前面4个方法BuildHostConfiguration() CreateHostingEnvironment()CreateHostBuilderContext()BuildAppConfiguration()所加工出来的各种信息。
services.AddSingleton<IHostingEnvironment>(_hostingEnvironment);
services.AddSingleton<IHostEnvironment>(_hostingEnvironment);
services.AddSingleton(_hostBuilderContext);
services.AddSingleton(_ => _appConfiguration);
Host的IHostApplicationLifetime和IHostLifetime这两个接口可以用来进行应用程序的生命周期管理。
这里不细究,详情可参考 探索 ASP.Net Core 3.0系列五:引入IHostLifetime并弄清Generic Host启动交互
services.AddSingleton<IHostApplicationLifetime, ApplicationLifetime>();
services.AddSingleton<IHostLifetime, ConsoleLifetime>();
接下来几句话 分别是:
注册IHost进服务容器,IHost的默认实现是一个内部类Host
注册Options(一个类似Configuration功能的服务,这里不细讲)
注册默认日志容器
services.AddSingleton<IHost, Internal.Host>();
services.AddOptions();
services.AddLogging();
后面是调用_configureServicesActions列表把其他服务注册进来......这里打住,我们知道了在ConfigureServices中配置了很多东西就可以了。
Configure
configure方法用于指定应用程序如何响应HTTP请求。通过将中间件组件添加到IApplicationBuilder实例来配置请求管道。
可以配置跨域、静态文件访问、HTTP重定向、异常处理等,如下图所示

接下来请看.Net Core 3.1 ,Configure的的代码如下:主要参数是 IApplicationBuilder ,IWebHostEnvironment 。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
IWebHostEnvironment 包含各种配置中要使用到的环境变量。
IApplicationBuilder 是重点,Configure 方法 使用 IApplicationBuilder 来使用中间件,使用 app.Use______ 来注册中间件请求管道
IApplicationBuilder 的源码如下:......\aspnetcore-3.1.14\src\Http\Http.Abstractions\src\IApplicationBuilder
public interface IApplicationBuilder
{
IServiceProvider ApplicationServices { get; set; }
IDictionary<string, object> Properties { get; }
IFeatureCollection ServerFeatures { get; }
RequestDelegate Build();
IApplicationBuilder New();
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
}
先说注入的三个参数
ApplicationServices :获取或设置提供对应用程序服务容器的访问的 IServiceProvider 提供程序,为其他对象提供自定义支持的对象,可以参考 https://www.cnblogs.com/watermoon2/p/5075002.html。
Properties:获取可用于在中间件之间共享数据的 键/值 集合,Properties 是类型为 IDictionary<string,object>。
ServerFeatures:获取应用程序服务器提供的HTTP特性集。
然后是三个方法
Build():可以看到这个方法是一个委托,使用此委托来处理HTTP请求

New():创建一个 IApplicationBuilder 共享 Properties 的 IApplicationBuilder

Use():将中间件委托添加到应用程序的请求管道中。

以上合起来就是Configure方法会调用ServiceProvider所解析的相应的参数,再可以使用IApplicationBuilder将中间件添加到应用程序管道中。最终RequestDelegate由IApplicationBuilder构建并返回的。
最后用一张图总结一下HTTP请求在中间件管道中的流程:

【.Net Core】.Net Core 源码分析与深入理解 - 配置中心 Startup.cs (二)的更多相关文章
- Heritrix源码分析(十三) Heritrix的控制中心(大脑)CrawlController(二)
本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/650744 本博客已迁移到本人独立博客: http://www.yun5u. ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
HDFS源码分析数据块复制监控线程ReplicationMonitor(二)
- 学习JUC源码(3)——Condition等待队列(源码分析结合图文理解)
前言 在Java多线程中的wait/notify通信模式结尾就已经介绍过,Java线程之间有两种种等待/通知模式,在那篇博文中是利用Object监视器的方法(wait(),notify().notif ...
- springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)
在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
- netty源码分析之揭开reactor线程的面纱(二)
如果你对netty的reactor线程不了解,建议先看下上一篇文章netty源码分析之揭开reactor线程的面纱(一),这里再把reactor中的三个步骤的图贴一下 reactor线程 我们已经了解 ...
- RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)
在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...
- 【源码分析】FastJson全局配置日期格式导致@JSONField(format = "yyyy-MM-dd")注解失效
出现的问题 我全局配置的时间格式是:yyyy-MM-dd HH:mm:ss @JSONField注解配置的时间格式是:yyyy-MM-dd 最终的返回结果是:yyyy-MM-dd HH:mm:ss 问 ...
- Java ArrayList源码分析(有助于理解数据结构)
arraylist源码分析 1.数组介绍 数组是数据结构中很基本的结构,很多编程语言都内置数组,类似于数据结构中的线性表 在java中当创建数组时会在内存中划分出一块连续的内存,然后当有数据进入的时候 ...
随机推荐
- 【转帖】千亿参数大模型首次被撬开!Meta复刻GPT-3“背刺”OpenAI,完整模型权重及训练代码全公布
https://cloud.tencent.com/developer/article/1991011 千亿级参数AI大模型,竟然真的能获取代码了?! 一觉醒来,AI圈发生了一件轰动的事情-- Met ...
- 机器学习从入门到放弃:卷积神经网络CNN(一)
一.前言 在上一篇中我们使用全连接网络,来构建我们的手写数字图片识别应用,取得了很好的效果.但是值得注意的是,在实验的最后,最后我们无论把 LOSS 优化到如何低,似乎都无法在测试数据集 test d ...
- 【VictoriaMetrics】一个小优化:循环改查表,性能提升56.48 倍
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 做了一个 vm-storage 数据文件 merge 的工 ...
- NSSCTF Round#17 Basic CRYPTO
Level_1 题目 Level_1.py(我把参数整理了一下,看着舒服) #真签到题 from Crypto.Util.number import bytes_to_long, getPrime f ...
- C# 中判断List集合是否为空
判断List集合是否为空,可以使用Count和Any,下面是其使用场景(别人总结)
- 【Mysql】复合主键和联合主键的区别
复合主键: create table index_test ( a int not null, b int not null, c int not null, d int null, primary ...
- 4.5 C++ Boost 文件目录操作库
Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量.可移植.高效的C应用程序.Boost库可以作为标准C库的后备,通常被称为准标准 ...
- 5.1 C++ STL 集合数据容器
Set/Multiset 集合使用的是红黑树的平衡二叉检索树的数据结构,来组织泛化的元素数据,通常来说红黑树根节点每次只能衍生出两个子节点,左面的节点是小于根节点的数据集合,右面的节点是大于根节点的集 ...
- 部署MooseFS分布式文件系统
MooseFS是一个分布式文件系统,其本身具有高可用性,高拓展性,开放源代码,高容错,等在数据的读写性能方面,通过dd测试,MooseFS也就是写入的速度稍微好于NFS,读上没有差别. MooseFS ...
- C/C++ 反汇编:针对加减乘除的还原
算术运算通常是指,加减乘除四则运算,而计算机中的四则运算与数学中的有所不同,同样是实现算术运算,高级语言与汇编语言的实现思路完全不同,往往一个简单的减法运算,都要几条指令的配合才能得出计算结果,而为了 ...