Kestrel 服务器源码解读和 IOC 容器依赖注入 DI
源码分析
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
CreateDefaultBuilder 方法
-
启动必须的配置:比如监听的端口,url 地址等。
-
程序自定义配置,从 appsettings.json、appsettings.[EnvironmentName].json、环境变量、命令行参数和其他配置源中加载。
-
日志系统的配置:将日志记录输送发送到控制台等。
ConfigureWebHostDefaults 方法
- 指定和配置
web 服务器:将 Kestrel 服务器用作 web 服务器并启用 IIS 集成。
为什么要用 HostBuilder?
-
Host 的职责只是完成主机该有的功能。
-
因为 Host 创建过程非常复杂,所以它的创建及其配置由一个特定的 HostBuilder 类完成,它是 Host 的创建器(工厂)。
Asp.net Core 的启动步骤

Asp.net Core 主机内部的执行流程
public static IHostBuilder CreateHostBuilder(string[] args)
{
IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args);
hostBuilder.ConfigureAppConfiguration(configure =>
{
Console.WriteLine("1. ConfigureAppConfiguration");
});
hostBuilder.ConfigureHostConfiguration(configure =>
{
Console.WriteLine("2. ConfigureHostConfiguration");
});
hostBuilder.ConfigureServices(configure =>
{
Console.WriteLine("3. ConfigureServices");
});
hostBuilder.ConfigureWebHostDefaults(webBuilder =>
{
Console.WriteLine("4. ConfigureWebHostDefaults");
webBuilder.UseStartup<Startup>();
});
return hostBuilder;
}
// output : 4,2,1,3

.NetCore 内置容器
在 .NetCore 里面默认提供一个服务注册和获取的容器,为什么要用这个容器呢?
我们写完了各种对象,在使用的时候,肯定去 new,这个是经常的操作。
试想另一种情况:如果我们在一个系统中,用的对象非常多,你就得不断的去new对象。
问题:处处在new是不是很麻烦?扩展也是不现实的。
想法:能不能别人帮我new?我想用什么,就得到什么?我们是用对象容器,就是帮我们生成这些对象,
并且对对象的生命周期,统一管理。
好处:不仅能够精确的控制对象的生命周期,而且,还能自动的创建依赖对象
看一下的问题,接口类:
public interface IServiceA
{
void Operation();
}
public interface IServiceB
{
void Operation();
}
public interface IServiceC
{
void Operation();
}
public interface IServiceD
{
void Operation();
}
接口的实现:
/// <summary>
/// 服务A的实现
/// </summary>
public class ObjectA : IServiceA
{
public ObjectA()
{
Console.WriteLine("ObjectA is Created!");
}
public void Operation()=> Console.WriteLine("ObjectA.Operation() is Called!");
}
/// <summary>
/// 服务B的实现
/// </summary>
public class ObjectB : IServiceB
{
private readonly IServiceA serviceA;
public ObjectB(IServiceA service)
{
this.serviceA = service;
Console.WriteLine("ObjectB is Created!");
}
public void Operation()
{
Console.WriteLine("--------------------------------------------");
this.serviceA.Operation();
Console.WriteLine("ObjectB.Operation() is Called!");
}
}
/// <summary>
/// 服务C的实现
/// </summary>
public class ObjectC : IServiceC
{
private readonly IServiceB serviceB;
public ObjectC(IServiceB service)
{
this.serviceB = service;
Console.WriteLine("ObjectC is Created!");
}
public void Operation() => Console.WriteLine("ObjectC.Operation() is Called!");
}
/// <summary>
/// 服务D的实现
/// </summary>
public class ObjectD : IServiceD
{
private readonly IServiceA _serviceA;
private readonly IServiceB _serviceB;
private readonly IServiceC _serviceC;
public ObjectD(IServiceA serviceA, IServiceB serviceB, IServiceC serviceC)
{
this._serviceA = serviceA;
this._serviceB = serviceB;
this._serviceC = serviceC;
Console.WriteLine("ObjectD is Created!");
}
public void Operation()
{
Console.WriteLine("---------------------------------------");
this._serviceA.Operation();
this._serviceB.Operation();
this._serviceC.Operation();
Console.WriteLine("ObjectD.Operation() is Called!");
}
}
main 方法里
static void Main(string[] args)
{
ObjectA obj = new ObjectA(); //直接new 对象
IServiceA a = new ObjectA(); // 基于接口,半解耦
IServiceB b = new ObjectB(a);
IServiceC c = new ObjectC(b);
IServiceD d = new ObjectD(a,b,c)
}
问题:
-
以前方法对于对象之间的关联创建,非常麻烦。因为一个对象所关联的其他对象,必须全部提前创建。
-
这种需求,即使我们以前所学的工厂模式,也很难做到。
Nuget 引入 DI
using Microsoft.Extensions.DependencyInjection;
static void Main(string[] args)
{
//【1】创建服务容器
IServiceCollection services = new ServiceCollection();
//【2】注册服务
services.AddTransient<IServiceA, ObjectA>();
services.AddSingleton<IServiceB, ObjectB>();
services.AddScoped<IServiceC, ObjectC>();
services.AddTransient<IServiceD, ObjectD>();
//【3】创建服务提供者对象
IServiceProvider serviceProvider = services.BuildServiceProvider();
//【4】获取服务 - 可能在系统的其他地方
//IServiceA instanceA = serviceProvider.GetService<IServiceA>();
IServiceD instanceD = serviceProvider.GetService<IServiceD>();
// instanceA.Operation();
Console.Read();
}
引入 Ioc 概念
-
Ioc(Inverse of Control) 控制反转: 就是将对象的控制权由我们开发者转移到容器。
-
好处:开发者不用关注细节,只需要关注抽象接口,非常有利于组件化开发。
依赖注入 DI 和 Ioc 容器
基于 Ioc 容器的 DI 框架两大核心
-
服务注册
-
服务提供
DI : Dependency Injection 思想
- 服务的使用者基于一个容器(Container)来得到需要的对象,容器在这个对象过程中自动完成所有依赖对象的创建。
常见 DI 容器
-
Autofac
-
Unity
-
Spring.Net
Ioc 和 DI 的区别
-
Ioc :调用者不关心对象的创建,由 Ioc 容器完成,体现的是一种控制权的转移。
-
DI: 基于 Ioc 容器创建需要的对象,同时能够自动完成所依赖对象的创建。体现的是一种依赖对象自动的注入。
总结
ASPNETCore 程序启动的核心方法源码分析
-
CreateDefaultBuilder() 方法
-
ConfigureWebHostDefault() 方法
-
细化 ASP.NET Core 主机内部的执行流程
Ioc 容器的使用
-
IServiceCollection
-
服务注册的三种生命周期 Transient Singleton Scoped
-
IServiceProvider
-
GetService() 方法
依赖注入 DI
-
思想:体现的是对象创建中所依赖的对象的自动创建。
-
好处:让模块化开发更加富有弹性。
Kestrel服务器源码解读和IOC容器依赖注入DI源码分析
CreateDefaultBuilder方法启动必须的配置:比如监听的端口,
url地址等。程序自定义配置,从
appsettings.json、appsettings.[EnvironmentName].json、环境变量、命令行参数和其他配置源中加载。日志系统的配置:将日志记录输送发送到控制台等。
ConfigureWebHostDefaults方法web服务器:将Kestrel服务器用作web服务器并启用IIS集成。为什么要用
HostBuilder?Host的职责只是完成主机该有的功能。因为
Host创建过程非常复杂,所以它的创建及其配置由一个特定的HostBuilder类完成,它是Host的创建器(工厂)。Asp.net Core的启动步骤Asp.net Core 主机内部的执行流程.NetCore内置容器在
.NetCore里面默认提供一个服务注册和获取的容器,为什么要用这个容器呢?我们写完了各种对象,在使用的时候,肯定去
new,这个是经常的操作。试想另一种情况:如果我们在一个系统中,用的对象非常多,你就得不断的去new对象。
问题:处处在new是不是很麻烦?扩展也是不现实的。
想法:能不能别人帮我new?我想用什么,就得到什么?我们是用对象容器,就是帮我们生成这些对象,
并且对对象的生命周期,统一管理。
好处:不仅能够精确的控制对象的生命周期,而且,还能自动的创建依赖对象
看一下的问题,接口类:
接口的实现:
main方法里问题:
以前方法对于对象之间的关联创建,非常麻烦。因为一个对象所关联的其他对象,必须全部提前创建。
这种需求,即使我们以前所学的工厂模式,也很难做到。
Nuget引入DI引入
Ioc概念Ioc(Inverse of Control)控制反转: 就是将对象的控制权由我们开发者转移到容器。好处:开发者不用关注细节,只需要关注抽象接口,非常有利于组件化开发。
依赖注入
DI和Ioc容器基于
Ioc容器的DI框架两大核心服务注册
服务提供
DI:Dependency Injection思想常见
DI容器AutofacUnitySpring.NetIoc和DI的区别Ioc:调用者不关心对象的创建,由Ioc容器完成,体现的是一种控制权的转移。DI: 基于Ioc容器创建需要的对象,同时能够自动完成所依赖对象的创建。体现的是一种依赖对象自动的注入。总结
ASPNETCore程序启动的核心方法源码分析CreateDefaultBuilder()方法ConfigureWebHostDefault()方法细化
ASP.NET Core主机内部的执行流程Ioc容器的使用IServiceCollection服务注册的三种生命周期
TransientSingletonScopedIServiceProviderGetService()方法依赖注入
DI思想:体现的是对象创建中所依赖的对象的自动创建。
好处:让模块化开发更加富有弹性。