前面分享了.net core Program类的启动过程已经源代码介绍,这里将继续讲Startup类中的两个约定方法,一个是ConfigureServices,这个方法是用来写我们应用程序所依赖的组件。另一个Configure,它是我们MVC请求的中间件方法,也就是我们每个请求来要执行的过程都可以写在这个方法里面。
      为什么说Startup类中的两个方法是基于约定的呢?其实是这样的,在.net core Program类Main方法中有个调用了Run方法这个方法从IServiceCollection容器中拿到一个IStartup类型的实例然后调用了IStartup中定义的两个方法法,如果我们的Startup类是实现了这个接口的类 那么就不是基于约定了,直接就可以使用,但是我们发现在vs给我们生成的Startup类并没有实现任何接口,所以就不会是IStartup类型,那么内部是如何去做的呢?  其实是这样的,在注册Startup实例的时候还有个类型叫做ConventionBasedStartup从名称上解读这个类就是转换为基础的Startup,其实却是也是这样的,这个类中是实现了IStartup接口,它的两个方法中分别调用了各自的对用委托,这些委托实际执行的就是我们Startup类中定义的两个方法,请看源代码:

 public class ConventionBasedStartup : IStartup
{
private readonly StartupMethods _methods; public ConventionBasedStartup(StartupMethods methods)
{
_methods = methods;
} public void Configure(IApplicationBuilder app)
{
try
{
_methods.ConfigureDelegate(app);
}
catch (Exception ex)
{
if (ex is TargetInvocationException)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
throw;
}
} public IServiceProvider ConfigureServices(IServiceCollection services)
{
try
{
return _methods.ConfigureServicesDelegate(services);
}
catch (Exception ex)
{
if (ex is TargetInvocationException)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
throw;
}
}
}

  现在Startup类的方法说清楚了,我们具体来说说方法中的内容,首先说ConfigureServices(IServiceCollection services),这个方法的参数是约定好的,不能随意改变,里面的IServiceCollection接口其实就是我们依赖注入的容器,说的再直白一点就是我们整个MVC所需要的实例都由IServiceCollection所管理,IServiceCollection有几个重要的扩展方法,他们都是定义在ServiceCollectionServiceExtensions静态类中,AddTransient方法,表示用这个方法添加到IServiceCollection容器的实例在需要注入的实例中都是一个全新的实例,AddScoped方法,这个方法表示在一次请求的生命周期内共用一个实例,AddSingleton方法,这个方法表示整个程序共用一个实例,例如日志服务,IConfiguration服务等都属于典型Singleton。请看例子:

 public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<TransientService>();
services.AddTransient<ServiceDemo1>();
services.AddTransient<ServiceDemo2>();
} public void Configure(IApplicationBuilder app, ServiceDemo1 demo1, ServiceDemo2 demo2 )
{
demo1.Test();
demo2.Test();
app.Run(async (HttpContext context) =>
{
await context.Response.WriteAsync("test successd");
});
}
}
public class TransientService
{
private int _updateCount;
public int GetUpdateCount()
{
this._updateCount = this._updateCount + 1;
return this._updateCount;
}
}
public class ServiceDemo1
{
private readonly TransientService _service;
public ServiceDemo1(TransientService service)
{
_service = service;
}
public void Test()
{
Console.WriteLine($"我是demo1的计数:{this._service.GetUpdateCount()}");
}
}
public class ServiceDemo2
{
private readonly TransientService _service;
public ServiceDemo2(TransientService service)
{
_service = service;
}
public void Test()
{
Console.WriteLine($"我是demo2的计数:{this._service.GetUpdateCount()}");
}
}

  上面的例子中会产生一下结果,可以看得出来这两个注入的TransientService都是全新的实例

如果我们稍微改变一下注入的方法,将原本的 services.AddTransient<TransientService>();改成services.AddScoped<TransientService>();就会产生如下结果:

这个能说明什么呢,我们有两次注入  这个就表示TransientService保持了之前demo1的状态  demo1和demo2是可以共用这个实例来传输数据的,AddSingleton方法理解起来比较简单就不过多絮叨了,上面已经说明。

接下来再来说说Startup类中的Configure方法,Configure方法中的参数是可以变化的,也就是说你可以用依赖注入的方法在参数中注入你想要注入的实例,前面说了 这个方法是我们请求的中间件方法,这个方法中会整合我们注入的IApplicationBuilder 中调用的各种Use方法中定义的中间件  并不是说这里面定义的代码每次请求都会被执行,这个概念一定要搞清楚,Configure方法只会在启动的时候执行一次,后面就不会再执行了,Configure方法只是让我们可以定义整个MVC的处理请求的执行顺序,具体的可以看看官方的文档https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-2.2

其实中间件都是由IApplicationBuilder 所管理的ApplicationBuilder类实现了IApplicationBuilder 接口中的方法,看到ApplicationBuilder中的源代码中有个属性_components 它是一个IList<Func<RequestDelegate, RequestDelegate>>类型的委托容器,容器中的委托就是请求过来需要执行的中间件委托,当你在Configure方法中调用app.UseXXX的时候就会被注册到这个容器中去,然后请求过来就按照顺序执行容器中的每一个委托,所以这里就解释了前面说的Configure方法只会被执行一次的说法。下面也贴一下ApplicationBuilder类的源代码:

 public class ApplicationBuilder : IApplicationBuilder
{
private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>(); public IServiceProvider ApplicationServices
{
get
{
return GetProperty<IServiceProvider>(Constants.BuilderProperties.ApplicationServices);
}
set
{
SetProperty(Constants.BuilderProperties.ApplicationServices, value);
}
} public IFeatureCollection ServerFeatures => GetProperty<IFeatureCollection>(Constants.BuilderProperties.ServerFeatures); public IDictionary<string, object> Properties
{
get;
} public ApplicationBuilder(IServiceProvider serviceProvider)
{
Properties = new Dictionary<string, object>(StringComparer.Ordinal);
ApplicationServices = serviceProvider;
} public ApplicationBuilder(IServiceProvider serviceProvider, object server)
: this(serviceProvider)
{
SetProperty(Constants.BuilderProperties.ServerFeatures, server);
} private ApplicationBuilder(ApplicationBuilder builder)
{
Properties = new CopyOnWriteDictionary<string, object>(builder.Properties, StringComparer.Ordinal);
} private T GetProperty<T>(string key)
{
if (!Properties.TryGetValue(key, out object value))
{
return default(T);
}
return (T)value;
} private void SetProperty<T>(string key, T value)
{
Properties[key] = value;
} public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
_components.Add(middleware);
return this;
} public IApplicationBuilder New()
{
return new ApplicationBuilder(this);
} public RequestDelegate Build()
{
RequestDelegate requestDelegate = delegate (HttpContext context)
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
};
foreach (Func<RequestDelegate, RequestDelegate> item in _components.Reverse())
{
requestDelegate = item(requestDelegate);
}
return requestDelegate;
}
}

好啦,这篇关于Startup类就算介绍完成了,下篇开始正式介绍MVC

												

.net core mvc启动顺序以及主要部件3-Startup的更多相关文章

  1. .net core mvc启动顺序以及主要部件2

    原文:.net core mvc启动顺序以及主要部件2 前一篇提到WebHost.CreateDefaultBuilder(args)方法创建了WebHostBuilder实例,WebHostBuil ...

  2. .net core mvc启动顺序以及主要部件1

    原文:.net core mvc启动顺序以及主要部件1 首先我是新人一个写这些东西也是为了增加记忆,有不对的地方请多多指教. 说回正题,打开Program.cs文件,看到在有个CrateWebHost ...

  3. .net core mvc启动顺序以及主要部件4-MVC

    前面三章已经把MVC启动过程以及源代码做了讲解,本章开始正式MVC,mvc全称叫model view controller,也就是把表现层又细分三层,官网的图片描述: 默认创建了一个.net core ...

  4. PCB MVC启动顺序与各层之间数据传递对象关系

    准备着手基于MVC模式写一套Web端流程指示查看,先着手开发WebAPI打通数据接口,后续可扩展手机端 这里将MVC基本关系整理如下: 一.MVC启动顺序 二.MVC各层之间数据传递对象关系

  5. ASP.NET Core MVC 源码学习:MVC 启动流程详解

    前言 在 上一篇 文章中,我们学习了 ASP.NET Core MVC 的路由模块,那么在本篇文章中,主要是对 ASP.NET Core MVC 启动流程的一个学习. ASP.NET Core 是新一 ...

  6. 第二十一节:Asp.Net Core MVC和WebApi路由规则的总结和对比

    一. Core Mvc 1.传统路由 Core MVC中,默认会在 Startup类→Configure方法→UseMvc方法中,会有默认路由:routes.MapRoute("defaul ...

  7. asp.net core mvc剖析:启动流程

    asp.net core mvc是微软开源的跨平台的mvc框架,首先它跟原有的MVC相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如taghelper,viewcomponent,D ...

  8. 解说asp.net core MVC 过滤器的执行顺序

    asp.net core MVC 过滤器会在请求管道的各个阶段触发.同一阶段又可以注册多个范围的过滤器,例如Global范围,controller范围等.以ActionFilter为例,我们来看看过滤 ...

  9. linux下使用supervisor启动.net core mvc website的配置

    发布好的asp.net core mvc项目, 如果想在window或linux下的以控制台程序启动的话,可以用下面的命令 dotnet MyProject.dll --urls="http ...

随机推荐

  1. html5表单上传控件Files筛选指定格式的文件:accept属性过滤excel文件

    摘自:http://blog.csdn.net/jyy_12/article/details/9851349 (IE9及以下不支持下面这些功能,其它浏览器最新版本均已支持.) 1.允许上传文件数量 允 ...

  2. Python的字符串与字节码转换

    一张图弄懂python的字符串与字节码转换  

  3. PAT 乙级 1042.字符统计 C++/Java

    题目来源 请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串.字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个 ...

  4. jupyter配置成coding神器

    参考链接: [1]http://resuly.me/2017/11/03/jupyter-config-for-windows/ [2]主题更换 切换主题:jt 主题名 -T 主题种类:chester ...

  5. Idea如何快速生成Junit测试类

    测试是保证代码必不可少的环节,自己构建测试方法太慢,并且命名也不规范,idea中提供了,一键构建测试结构的功能... 2.步骤 1.在需要做测试的类的当前窗口,直接按快捷键:按ctrl+shift+t ...

  6. 201871010108-高文利《面向对象程序设计(java)》第二周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...

  7. Java多线程编程核心技术-第3章-线程间通信-读书笔记

    第 3 章 线程间通信 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大 ...

  8. java GC jvm 内存分布 和新生代,老年代,永久代,(详细)

    如果大家想深入的了解JVM,可以读读周志明<深入理解Java虚拟机:JVM高级特性与最佳实践> 需要掌握的东西,包括以下内容.判断对象存活还是死亡的算法(引用计数算法.可达性分析算法).常 ...

  9. Debian 安装docker

    1 $ curl -fsSL get.docker.com -o get-docker.sh 2 $ sudo sh get-docker.sh --mirror Aliyun

  10. filbeat遇到的坑(运行久和文件数据量多时候 )

    1.现像,吃cpu,&& io 过程:量大的时候发现在filbeat很吃io, 原因: 日志量文件数太多,因为日志是2m一个文件 ,一天几十个G 开始怀疑是centos  6的问题,, ...