点击上方蓝字"小黑在哪里"关注我吧

1.起源?

为什么会有这篇文章呢? 源于我看了老A的aspnet core 3 框架揭秘[1]请求管道 篇产生的疑惑?

三点疑惑:

  1. Singleton服务中注入Scoped服务产生内存泄露?
  2. 关于中间件的生命周期是Singleton的?
  3. 怎么避免中间件、Singleton服务中使用Scoped服务不产生内存泄漏?

2.知识面覆盖

示例中会覆盖到aspnet core相关的配置、依赖注入(周期)、中间件的知识点,若不清楚的需要先看看这些概念以及基本使用。

收获:和我一起带着以上三个问题来进行验证也就会收获到相关知识点。

3. 测试环境准备

创建三个服务:

1. IOrderAppService(singleton)2. IProductAppService(scoped)3. ITransientTestAppService(transient)

创建请求控制器:

public class ProductController : Microsoft.AspNetCore.Mvc.Controller{    private int time = 1;    private readonly IHostApplicationLifetime _lifetime;    public ProductController(IProductAppService productAppService1,        IProductAppService productAppService2,        IOrderAppService orderAppService1,        IOrderAppService orderAppService2,        ITransientTestAppService transientTestAppService1,        ITransientTestAppService transientTestAppService2,        IHostApplicationLifetime lifetime)    {        _lifetime = lifetime;    }

    [HttpGet]    [Route("/get")]    public Task<string> Get()    {        return Task.FromResult($"第{time++}次请求成功!");    }

    [HttpGet]    [Route("/stop")]    public void Stop() => _lifetime.StopApplication();}

创建中间件:

public sealed class UrlMiddleware{    private int times = 1;    private readonly RequestDelegate _next;    public UrlMiddleware(RequestDelegate next,        IProductAppService productAppService,        ITransientTestAppService transientTestAppService)    {        //构造中的productAppService服务是由IApplicationBuilder.ApplicationServices根容器创建的        _next = next;    }

    public async Task InvokeAsync(HttpContext context,IProductAppService productAppService,ITransientTestAppService transientTestAppService)    {        //invoke中的productAppService其实是context.RequestServices子容器创建的。        //这里的context.RequestServices子容器也是由IApplicationBuilder.ApplicationServices根容器创建来的。        var productService = context.RequestServices.GetRequiredService();//使用解析的方式和上面方法中注入进来是一样的作用,切记是使用子容器RequestServices解析        Console.WriteLine($"请求第{times++}次进入UrlMiddleware中间件。hash:{this.GetHashCode()}");await _next(context);    }}

注册服务:

service.AddTransient()       .AddScoped()       .AddSingleton();

这里若使用的IMiddleware创建中间件也记得需要注册。

4.开始验证

4.1 关于中间件的生命周期是Singleton的?

这里我们先验证下这个问题。为第一个问题做铺垫。

文章中我就不做过多的代码介绍,主要是对代码片段的解释,有需要的可以看源代码[2]

  • 开始运行:

    dotnet run

    会注意到中间件构造中注入的服务会在项目启动完成前就会创建完成。

  • 开始请求:

    输入http://localhost:5002/get, 这是因为配置了 UseUrls,也可以直接使用UseSetting("urls"")

    使用UseSetting的key默认定义在WebHostDefaultsHostDefaults

    为了验证问题我们请求两次。

    开始请求

    中间件是否是单例

    分析总结:从两次请求中可以确定不管是强类型的中间件还是按照约定(弱类型)的中间件都是单例的(Singleton)

    这里穿插一下关于Singleton\Scoped\Transient生命周期控制台输出:分析总结:

    • Scoped服务请求中只会创建一次并且请求完成后释放
    • Transient服务每一次都会重新创建并且请求完成后全部释放
    • Singleton整个应用程序周期内只会创建一次并且直到应用程序关闭时才会释放(慎用慎选择)

4.2 Singleton服务中注入Scoped服务产生内存泄露?

调用http://localhost:5002/stop 进行远程关闭应用程序。控制台输出:分析总结:中间件构造中注入scoped服务时会跟随根容器的释放才会释放,相当于说就是会在整个应用程序生命周期中存在,所以也就容易导致内存泄漏

从这里还没能表现出构造中的服务和invoke方法中的服务区别。。。下面进行验证:

分析总结:

从图中画线中能看出请求完成后只有invoke方法中的scoped\transient服务释放了,中间件构造中的任何类型服务都不会得到释放,所以需要在中间件使用关于非singleten服务时在方法中进行注入,不要使用构造注入,这是为什么呢?

其实invoke方法中的服务是通过子容器(context.RequestServices)创建而来的,所以跟随请求完成子容器释放也就会释放掉子容器内创建出的服务。context.RequestServices是由IApplicationBuilder.ApplicationServices根容器创建而来的。

以上内容也只是使用中间件这种特殊来进行了测试,那么怎么来验证Singleton服务中注入scoped来进行验证呢?自行尝试?应该是不可以的哦?`ServiceProviderOptions`。

4.3 怎么避免中间件、Singleton服务中使用Scoped服务不产生内存泄漏?

其实4.2中已经有了答案了。

如何避免?

在中间件中使用invoke方法中注入服务或者使用context.RequestServices.GetRequiredService<>();来解析服务,不推荐(反模式)。

在singleton服务中使用使用IServiceProvider来创建子容器解析。

要是以上内容有什么不对的地方欢迎也希望得到指点。

5 总结

从自己看书到自己写代码来验证以及写这篇文章多多少少算花了两天的时间,但是感觉还是有收获的,算是搞清楚了一些问题。

强烈推荐老A的 aspnet core 3 框架揭秘[3] ,对深入aspnet core有很大的帮助,能 够对aspnet core中的知识点有一个大体轮廓。

参考资料

[1]

aspnet core 3 框架揭秘: https://www.cnblogs.com/artech/

[2]

源代码: https://github.com/jonny-xhl/my-demo/tree/master/src/middleware/Jonny.AllDemo.SingleMiddleware

[3]

aspnet core 3 框架揭秘: https://www.cnblogs.com/artech/

如果本文对您有用,

不妨点个“”或者转发朋友圈支持一下

aspx 使用什么中间件_.NET Core中间件与依赖注入的一些思考相关推荐

  1. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  2. ASP.NET Core 中的依赖注入

    什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要依赖于抽象,不要依赖于具体.而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖 ...

  3. 拥抱.NET Core系列:依赖注入(2)

    上一篇"拥抱.NET Core系列:依赖注入(1)大体介绍了服务注册.获取和生命周期,这一篇来做一些补充.由于内容跨度大(.NET Core.ASP.NET Core),所以文章并不是非常的 ...

  4. winform防止sqlserver注入_ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

  5. .NET Core中间件与依赖注入的一些思考

    点击上方蓝字"小黑在哪里"关注我吧 1.起源? 为什么会有这篇文章呢? 源于我看了老A的aspnet core 3 框架揭秘[1] 请求管道 篇产生的疑惑? 三点疑惑: Singl ...

  6. 东方通 中间件_东方通:中间件国产替代进程中的艰难领军者

    引言 东方通自1992年成立以来,一直深耕基础软件中间件的产品及相关技术研发,为国产中间件的开创者,连续十几年保持中间件市场占有率国内厂商第一.其时,国外的中间件也才开始起步,可以说与国际厂商站在了同 ...

  7. ASP.NET Core 2.0 依赖注入

    问题 如何使用 ASP.NET Core 服务容器进行依赖注入? 答案 创建一个服务 public interface IGreetingService { string Greet(string t ...

  8. ASP.NET Core依赖注入初识与思考

    一.前言 在上一篇中,我们讲述了什么是控制反转(IoC)以及通过哪些方式实现的.这其中,我们明白了,「控制反转(IoC)」 是一种软件设计的模式,指导我们设计出更优良,更具有松耦合的程序,而具体的实现 ...

  9. dotNET Core 3.X 依赖注入

    如果说在之前的 dotNET 版本中,依赖注入还是个比较新鲜的东西,那么在 dotNET Core 中已经是随处可见了,可以说整个 dotNET Core 的框架是构建在依赖注入框架之上.本文说说对 ...

最新文章

  1. (原)使用mkl计算特征值和特征向量
  2. Java运行时动态加载类之ClassLoader加载class及其依赖jar包
  3. CSS固定背景的图片
  4. Codeforces 994B. Knights of a Polygonal Table
  5. 工作112:vue路由跳转错误:Error: Redirected when going from “/login“ to “/home“ via a navigation guard.
  6. Eclipse 使用 CodeMix 插件 开发 Vue.js
  7. 数据结构pta选择判断复习
  8. Scala中的Apply方法与伴生对象
  9. 【20171227】json
  10. xpath用于HTML文档通过元素,通过Xpath定位元素
  11. Java实现一个简单的两人五子棋游戏(二) 画棋盘
  12. 软件工程---客观题
  13. 100人PJ?へへ。バージョン1.0の反省書を書かなければなりません、今日。
  14. Hive_数据建模工具EZDML
  15. HTML设置圆角头像,圆角头像的制作
  16. SIP穿越NAT SIP穿越防火墙
  17. 深度学习分类类别不平衡_Github|类别不平衡学习资源(上)
  18. 关于union联合查询
  19. 一文了解 AlphaFold 2 背后的 PDB 蛋白质结构数据集
  20. 微信版“花呗”全面开放,人人都可以申请!

热门文章

  1. python怎么样才算入门编程-新手如何快速入门Python编程?听过来人说经验!
  2. python处理excel的工具-基于Python的Excel处理工具
  3. python基本语法语句-python学习笔记:基本语法
  4. 机器人编程语言python-10大热门机器人编程语言,你掌握了哪种?
  5. 用python画简单的动物-使用Python的turtle画小绵羊
  6. c+和python哪个快-C/C++比python快是什么意思?
  7. python教程是用什么博客写的-Python 有哪些好的学习资料或者博客?
  8. python下载后如何使用-如何使用Python通过HTTP下载文件
  9. python爬虫吧-python爬虫-贴吧
  10. python写一个游戏多少代码-Python项目实战之猜数字游戏(含实现代码)