ASP.NET Core 启动和配置
- Program类,Main方法
- Startup类
其中很核心的思想是(Dependency Injection,依赖注入);
还有IoC容器(Inversion of Control,控制反转);
- 注册(services注册);
- 请求实例;
- 实例的生命周期;
其中,生命周期 1)Transient 注册的服务在每次被请求的时候都会生成一个新的实例; 2) Scoped .netcore 中有web请求,一个Web请求产生一个实例; 3) Singleton 服务的实例一旦被创建,以后的服务都只用这一个实例(一直存在),直到应用程序结束实例才被销毁;
依赖注入的好处是,①解耦,没有强依赖;(利于单元测试)②不用去管生命周期(实例的生命周期是由IOC容器来控制的);③类型之间没有依赖;
Program 类:Web程序的入口
Program 类的本质就是一个控制台应用,可以说做是.netcore web程序的入口。
其中的 Main 方法是 Web 应用的入口方法。
我们可以在 Main方法中启动 Web 服务。
Program 类的源码
首先,Program 类中的 Main方法调用CreateWebHostBuilder(args).Build().Run() 方法。
该方法的最终目的和意义就是使用 CreateWebHostBuilder 方法返回的 IWebHostBuilder 接口类型对象来构建(Build)一个 WebServe 然后运行(Run)这个 WebServe。
|
|
CreateWebHostBuilder 方法返回的对象是静态类WebHost 的静态方法 CreateDefaultBuilder 方法返回的。
在 CreateWebHostBuilder 方法中我们可以看到一个 lambda 表达式,他返回了 WebHost.CreateDefaultBuilder(args).UseStartup();
CreateDefaultBuilder方法的源码
反编译 WebHost.CreateDefaultBuilder 方法的源码,我们先来看一下完整的代码实现。
我们发现 CreateDefaultBuilder 方法首先 new 了一个 WebHostBuilder 类型的对象 var builder = new WebHostBuilder(); 。
而 WebHostBuilder 类就实现了我们所需要返回的的 IWebHostBuilder 接口类型。
|
|
ConfigureWebDefaults 方法的源码
在方法的末尾,调用了 ConfigureWebDefaults(builder); 方法。
该方法详细地配置了默认的 builder 的各种设置,我们也来看一下完整的源码实现。
|
|
builder 的默认配置
1.使用 Kestrel Web Serve
如上代码所示,我们可以看到 builder 首先调用了 UseKestrel 方法,配置了 Kestrel 服务器。
2.IIS 集成
然后 builder 使用了 UseIIS().UseIISIntegration(); 这两个方法配置了 IIS 服务器。
UseIISIntegration 方法和前者的区别就是它允许 IIS 通过 Windows 的验证来到 Kestrel 服务器,这有利于构建内网的 Web 应用。
而在项目的 csproj 文件中我们可以看到声明了 InProcess 。
在 InProcess 模式下 IIS 会和 Web 程序运行在一个系统内。而与之相对的是 OutOfProcess 模型。
OutOfProcess 模式会把请求转发给 Kestrel 服务器。相比 OutOfProcess 这种分开的模式,InProcess 模式提高了性能。
3.Logger
回到 CreateDefaultBuilder 方法,这段代码配置了 ConfigureLogging,将 logger 输出到 Console,Debug 和 EventSourceLogger。
4.IConfiguration 接口
我们可以通过实现 IConfiguration 接口的类型对象里获取一些需要的配置信息。
前面提到 CreateDefaultBuilder 方法首先 new 了一个 WebHostBuilder 类型的对象。 var builder = new WebHostBuilder();
而 WebHostBuilder 类型就持有一个 IConfiguration 接口类型的成员字段 _config。
IConfiguration 接口类型也很简单,其中的 string this[string key]{get; set;} 就是以 key-value 的形式,通过string来获取配置信息,封装的其他方法就在此省略了。
配置信息首先从json文件中获取,我们的项目中存在着 appsettings.json 和 appsettings.Development.json 两个默认的 json 文件。
打开 appsettings.json 文件,我们可以看到默认生成的配置如下所示。
|
|
获取配置信息的方法和顺序
回到 CreateDefaultBuilder 方法,我们可以找到这一句代码。
|
|
其中,config 是 builder.ConfigureAppConfiguration() 调用的 lambda 表达式参数 (hostingContext, config) =>{} ,其设置了配置文件的具体名称。
注意,config 调用 AddJsonFile 方法,调用了两次,第二个 json 文件是系统环境变量为名的json文件,默认是 Devolopment,也就是前面提到的 appsettings.Development.json。
如果两个文件有相同的属性,后者就会覆盖掉前者的设置。但是 CreateDefaultBuilder 方法的代码中还有一句设置 config.AddEnvironmentVariables();
这一句代码是设置系统环境变量,如果有和以上配置文件相同的属性,也会覆盖的前者的设置。
在系统环境变量之后又有一句 config.AddCommandLine(args); ,命令行中如果有和以上配置文件相同的属性,也会覆盖的前者的设置。
所以最终的属性的覆盖顺序为 appsettings.json -> appsettings.{env.EnvironmentName}.json -> AddEnvironmentVariables -> AddCommandLine
UseStartup<> 方法
回到 Program 类的 CreateWebHostBuilder 方法,我们可以发现 WebHost.CreateDefaultBuilder(args).UseStartup(); 。
其调用了 UseStartup<> 方法。 UseStartup() 指定 Startup 为 Startup 类,以该类来配置整个 Web 应用,如注册服务、使用中间件等等。
然后CreateWebHostBuilder 方法返回的 builder 回到 Main 方法,Build 后再调用 Run 方法,我们的 Web 应用就可以监听 Http/Https 的请求了。
Progarm 这个类主要是为了配置我们的 Web 应用的基础设施,如 Http 服务器以及如何集成到 IIS 等。