asp.net core mvc 是微软开源的跨平台的 mvc 框架,首先它跟原有的 MVC 相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如 taghelper,viewcomponent,DependencyInjection 等,现在开始 asp.net core mvc 剖析之旅。
任何应用程序都有入口点,MVC 中也如此,通过新框架创建的 MVC 程序里,有一个特殊的文件 Program.cs,里面包含了一个 Main 方法,这个方法相信大家都不陌生,控制台应用程序也有类似的 Main 方法,这个方式其实就是 MVC 程序的入口方法,那我们来看一下这个方法里主要做了什么工作?
- public static void Main(string[] args)
- {
- var host = new webHostBuilder()
- .UseKestrel()
- .UseContentRoot(Directory.GetCurrentDirectory())
- .UseIISIntegration()
- .UseStartup<Startup>()
- .Build();
- host.Run();
- }
从上面的代码我们可以看出,通过 WebHostBuilder 类 Build 了一个 IWebHost 对象,然后调用 host.Run 方法完成应用程序启动。那我们再来看一下,WebHost 是如何被 Build 出来的。在 Hosting 项目中最终找到了 WebHostBuilder 类的踪影,Build 方法里有几句关键代码:
- //创建应用程序依赖注入的IServiceCollection对象,这个后面会单独去讲解
- var hostingServices = BuildHostingServices();
- var hostingContainer = hostingServices.BuildServiceProvider();
- //实例化WebHost对象
- var host = new WebHost(hostingServices, hostingContainer, _options, _config);
- //初始化
- host.Initialize();
在 WebHost 类中找到 Initialize() 方法,方法里调用了 BuildApplication 完成 http 请求处理管道的构建。我们来看下构建处理管道的过程
- //这个方法其实是调用程序里Startup类中的ConfigureServices方法,完成服务依赖注册
- EnsureApplicationServices();
- //IServer的相关操作
- EnsureServer();
- var builderFactory = _applicationServices.GetRequiredService();
- var builder = builderFactory.CreateBuilder(Server.Features);
- builder.ApplicationServices = _applicationServices;
- var startupFilters = _applicationServices.GetService>();
- Action configure = _startup.Configure;
- foreach (var filter in startupFilters.Reverse())
- {
- //调用Startup类中的Configure方法注册处理中间件(middleware)
- configure = filter.Configure(configure);
- }
- configure(builder);
到这里中终于明白 startup.cs 类作用了。完成了基本的配置后,应用程序就可以启动了。
WebHost.Run 方法定义是在 WebHostExtensions 中,作为扩展方法存在的,Run 方法中调用了 WebHost 的 Start 方法,WebHost 的 Start 方法直接调用了 IServer 的 Start 方法进行服务启动
- Server.Start(new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory));
_application:http 请求处理管道
httpContextFactory:httpcontext 工厂,每个 http 请求都会对应一个 httpcontext 对象,这个 httpcontext 就由这个工厂进行创建,这个工厂在 HttpAbstractions 项目中。
IServer 启动方法里会启动请求监听,当 http 请求过来后,首先调用 HostingApplication(IHttpApplication 类型) 的 CreateContext 创建 HttpContext 对象,CreateContext 会依赖上面提到的 httpContextFactory,HttpContext 创建后就会调用 HostingApplication 的 ProcessRequestAsync 方法进行请求处理:
- public Task ProcessRequestAsync(Context context)
- {
- return _application(context.HttpContext);
- }
ProcessRequestAsync 方法里很简单,直接把 http 请求放入 http 处理管道进行处理。
下一篇文章会介绍 KestrelServer 如何监听请求,并交给处理管道进行处理的。
来源: