【.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中当创建数组时会在内存中划分出一块连续的内存,然后当有数据进入的时候 ...
随机推荐
- [转帖]在龙芯3A5000上测试SPEC CPU 2006
https://baijiahao.baidu.com/s?id=1707601012673143593&wfr=spider&for=pc 注:百家号中,一些文本.代码等的排版格式无 ...
- [转帖]Shell脚本中利用expect实现非交互式
https://developer.aliyun.com/article/885723?spm=a2c6h.24874632.expert-profile.295.7c46cfe9h5DxWK 简介: ...
- TypeScript枚举类型
枚举 简单理解就是将所有的情况列举出来. 枚举不是用来定义类型的哈.就是说枚举不是一种数据类型. enum xxx={ key1=value1, key2=value2, } 通过 xxx.key1的 ...
- ACME笔记(思维导图)
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯
- Go 泛型之明确使用时机与泛型实现原理
目录 一.引入 二.何时适合使用泛型? 场景一:编写通用数据结构时 场景二:函数操作的是 Go 原生的容器类型时 场景三:不同类型实现一些方法的逻辑相同时 三.Go 泛型实现原理 Stenciling ...
- layui之静态表格的分页及搜索功能以及前端使用XLSX导出Excel功能
LayUI官方文档:https://layui.dev/docs/2/#introduce XLSX NPM地址:https://www.npmjs.com/package/xlsx XLSX 使用参 ...
- 5.12 汇编语言:仿写While循环语句
循环语句(While)一种基本控制结构,它允许程序在条件为真的情况下重复执行一段代码块,直到条件为假为止.循环语句在处理需要重复执行的任务时非常有用,它可以让程序更加高效地处理大量数据或者重复性操作. ...
- Metasploit 生成带SSL加密载荷
1.下载证书.Impersonate_SSL模块,下载指定网站的证书. msf6> use auxiliary/gather/impersonate_ssl msf6 auxiliary(gat ...
- spring框架中RESTFUL接口相关注解
1.说明 springboot 是国内最常用的web框架,因为它的http server功能是最重要的.本文列举了一些现在通用的restful形式的接口所需要的注解 2.@RequestMapping ...
- 【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程
1.作品图 2.准备工作 目前网上能搜到的stable-diffusion-webui的安装教程都是Window和Mac M1芯片的,而对于因特尔芯片的文章少之又少,这就导致我们还在用老Intel 芯 ...