《ASP.NET Core 高性能系列》ASP.NET Core的启动过程(1)

原文: 《ASP.NET Core 高性能系列》ASP.NET Core的启动过程(1)

一、一切从头开始

简述:知道事情的真相就应该从头 开始,下面我们代码先行

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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>();
                 });
}

可见,关键是我们需要研究CreateHostBuilder整个方法内部做了什么,不要简单地看这个方法,真实情况涉及很深.本文简化很多问题来说明

二、先让我们熟悉几个数据结构

2.1 IHostBuilder (暂时写这一个,后续再增加)

复制代码
public interface IHostBuilder
{
    IDictionary<object, object> Properties
    {
        get;
    }
  //宿主程序的配置
    IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate);
  //应用程序的配置
    IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate);
  //添加service到容器
    IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate);
    IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);
  //覆盖用于创建ServiceProvider的工厂。
    IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory);
/  /配置依赖注入的容器
    IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate);

    IHost Build();
}
复制代码

得出简要的分析和猜测:CreateHostBuilder中设置Asp.net core中所需诸多原始素材:配置信息(包括环境等),IOC所需的种种素材,创建web程序所需的宿主WebHost然后将上面的素材同时传给WebHost.......

三、CreateDefaultBuilder方法内部做了什么

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public static IHostBuilder CreateDefaultBuilder( string [] args)
{
     HostBuilder hostBuilder = new HostBuilder();
     hostBuilder.UseContentRoot(Directory.GetCurrentDirectory());      //设置Host的配置信息
     hostBuilder.ConfigureHostConfiguration((Action<IConfigurationBuilder>) delegate (IConfigurationBuilder config)
     {
         config.AddEnvironmentVariables( "DOTNET_" );
         if (args != null )
         {
             config.AddCommandLine(args);
         }
     });      //设置应用程序的配置信息
     hostBuilder.ConfigureAppConfiguration((Action<HostBuilderContext, IConfigurationBuilder>) delegate (HostBuilderContext hostingContext, IConfigurationBuilder config)
     {
         IHostEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
         config.AddJsonFile( "appsettings.json" , optional: true , reloadOnChange: true ).AddJsonFile( "appsettings." + hostingEnvironment.EnvironmentName + ".json" , optional: true , reloadOnChange: true );
         if (hostingEnvironment.IsDevelopment() && ! string .IsNullOrEmpty(hostingEnvironment.ApplicationName))
         {
             Assembly assembly = Assembly.Load( new AssemblyName(hostingEnvironment.ApplicationName));
             if (assembly != null )
             {
                 config.AddUserSecrets(assembly, optional: true );
             }
         }
         config.AddEnvironmentVariables();
         if (args != null )
         {
             config.AddCommandLine(args);
         }
     }) //设置日志的相关配置       .ConfigureLogging((Action<HostBuilderContext, ILoggingBuilder>)delegate(HostBuilderContext hostingContext, ILoggingBuilder logging)
     {
         bool num = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
         if (num)
         {
             logging.AddFilter<EventLogLoggerProvider>((LogLevel level) => level >= LogLevel.Warning);
         }
         logging.AddConfiguration(hostingContext.Configuration.GetSection( "Logging" ));
         logging.AddConsole();
         logging.AddDebug();
         logging.AddEventSourceLogger();
         if (num)
         {
             logging.AddEventLog();
         }
     }).UseDefaultServiceProvider((Action<HostBuilderContext, ServiceProviderOptions>) delegate (HostBuilderContext context, ServiceProviderOptions options)
     {
         bool validateOnBuild = options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
         options.ValidateOnBuild = validateOnBuild;
     });
     return hostBuilder;
}

我们先总结一些知识点和注意事项

1.程序的默认的根目录采用了Directory.GetCurrentDirectory()也就是Environment.CurrentDirectory,那么这意味着我们在用其它程序启动应用时需要手动指定当前工作目录,避免发生变化.

2.asp.net core中两个路径的区别

?
1
2
ContentRoot:  C:\MyApp
WebRoot:      C:\MyApp\wwwroot

3.asp.net core中配置文件的优先级问题

命令行>环境变量>自我订制的配置(AddUserSecrets)>和当前环境相匹配的appsettings.json中的配置>大于appsettings.json中的配置

  关于AddUserSecrets是什么这里简单一言以蔽之:每个开发人员有自己特性的配置数据,这些配置信息仅仅属于个人,不能提交给团队成员,

  但是又不想不团队共有的配置所影响. 剩下的自行去了解,关键是上面的优先级

  和当前环境相匹配的appsettings.json如appsettings.Development.json

4.系统会默认添加日志行为如下

  a.windows会添加事件(level >= LogLevel.Warning)

  b.默认会将采用appsettings.json中Logging节点下的配置情况

  c.日志信息默认会显示咋控制台和调试中

四、 Startup 类

主要作用:配置服务和应用的请求管道。ASP.NET Core 按照约定命名为 Startup作为 Startup 类:

1.可选择性地包括 ConfigureServices 方法以配置应用的服务 。 服务是一个提供应用功能的可重用组件。

  在 ConfigureServices 中注册服务,并通过依赖关系注入 (DI) 或 ApplicationServices 在整个应用中使用服务 。


2.包括 Configure 方法以创建应用的请求处理管道。


在启动时,ASP.NET Core会调用 ConfigureServices 和 Configure:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Startup
{
     public Startup(IConfiguration configuration)
     {
         Configuration = configuration;
     }
     public IConfiguration Configuration { get ; }
     // 该方法会被运行时自动调用,通过此方法可将service添加到容器中.
     public void ConfigureServices(IServiceCollection services)
     {
         services.AddControllersWithViews();
     }
     // 该方法会被运行时自动调用. 使用此方法配置 HTTP request pipeline.
     public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
     {
         if (env.IsDevelopment())
         {
             app.UseDeveloperExceptionPage();
         }
         else
         {
             app.UseExceptionHandler( "/Home/Error" );
             // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
             app.UseHsts();
         }
         app.UseHttpsRedirection();
         app.UseStaticFiles();
         app.UseRouting();
         app.UseAuthorization();
         app.UseEndpoints(endpoints =>
         {
             endpoints.MapControllerRoute(
                 name: "default" ,
                 pattern: "{controller=Home}/{action=Index}/{id?}" );
         });
     }
}

Startup总结:

  从第一部分我们可以看到在程序启动时通过webBuilder.UseStartup<Startup>()将Startup指定给Host,

注意:Host能够提供 Startup 类构造函数可用的某些服务。 应用自身可通过 ConfigureServices方法 添加你需要的其他服务。

主机和应用提供的这些服务都可以在 Configure 和整个应用中使用。

使用泛型Host (IHostBuilder) 时,只能将以下服务类型注入 Startup 构造函数:
  IWebHostEnvironment
  IHostEnvironment
  IConfiguration

  未完待续,不足之处欢迎请指正.

猜你喜欢

转载自www.cnblogs.com/lonelyxmas/p/12292921.html