.NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(下)
06 | 作用域与对象释放行为
接下来,把服务切换为单例模式,通过工厂的方式
services.AddSingleton<IOrderService>(p => new DisposableOrderService());
启动程序,输出如下:
=======1==========
=======2==========
接口请求处理结束
可以看到代码实际上不会被释放
如果切换为瞬时模式,通过工厂的方式
services.AddTransient<IOrderService>(p => new DisposableOrderService());
启动程序,输出如下:
=======1==========
DisposableOrderService Disposed:12021664
=======2==========
接口请求处理结束
DisposableOrderService Disposed:3165221
DisposableOrderService Disposed:13048313
这里可以看到,获取三个服务并且释放掉
接下来把服务调整为自己创建,并注册进去
var service = new DisposableOrderService();
services.AddSingleton<IOrderService>(service);
同样我们也不会得到释放的输出
也就是说,通过这种方式注册,容器不会管理对象的生命周期
如何识别这个区别呢?
在控制器中注入 IHostApplicationLifetime 接口
这个接口的作用是用来管理整个应用程序的生命周期
它有一个方法 StopApplication
也就是说它可以把整个应用程序关掉
接着,通过手工关掉的方式看一下应用程序关闭时会不会把单例对象释放掉
[HttpGet]
public int Get([FromServices] IOrderService orderService,
[FromServices] IOrderService orderService2,
[FromServices]IHostApplicationLifetime hostApplicationLifetime,
[FromQuery]bool stop = false)
{
Console.WriteLine("=======1==========");
// HttpContext.RequestServices 是当前请求的一个根容器,应用程序根容器的一个子容器,每个请求会创建一个容器
using (IServiceScope scope = HttpContext.RequestServices.CreateScope())
{
// 在这个子容器下面再创建一个子容器来获取服务
var service = scope.ServiceProvider.GetService<IOrderService>();
var service2 = scope.ServiceProvider.GetService<IOrderService>();
}
Console.WriteLine("=======2==========");
if (stop)
{
hostApplicationLifetime.StopApplication();
}
Console.WriteLine("接口请求处理结束");
return 1;
}
首先用自己创建对象的方式
var service = new DisposableOrderService();
services.AddSingleton<IOrderService>(service);
启动程序
输入 ?stop=true
https://localhost:5001/weatherforecast?stop=true
输出如下:
...
DependencyInjectionScopeAndDisposableDemo.exe (进程 16884)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
如果单例由容器来管理,切换回普通注册方式
services.AddSingleton<IOrderService, DisposableOrderService>();
启动程序
输入 ?stop=true
https://localhost:5001/weatherforecast?stop=true
输出如下:
Application is shutting down...
接口请求处理结束
DisposableOrderService Disposed:23399238
对象释放,应用程序退出
这里说明单例的服务都是注册在根容器里面
根容器的释放意味着需要在整个应用程序退出时释放
这个时候它会释放自己所管理的所有的 IDisposable 的对象
这里面有一个非常需要注意的坑:
假如把服务注册成瞬时的
services.AddTransient<IOrderService, DisposableOrderService>();
然后又在根容器里面去获取这个对象
var s = app.ApplicationServices.GetService<IOrderService>();
这意味着在根容器去持续的创建 IOrderService,但是由于根容器只会在应用程序整个退出时回收,也就意味着这些对象会一直积累在应用程序内
调整控制器,不获取 IOrderService
[HttpGet]
public int Get(
[FromServices]IHostApplicationLifetime hostApplicationLifetime,
[FromQuery]bool stop = false)
{
if (stop)
{
hostApplicationLifetime.StopApplication();
}
return 1;
}
仅仅在根容器获取一次
var s = app.ApplicationServices.GetService<IOrderService>();
这样运行起来,每次请求(点击刷新)的话,整个输出是不会有内容的,因为我们没有在子容器里面去获取对象
也就是说,实现了 IDisposable 接口的服务,如果时注册瞬时的,又在根容器去做操作,它会一直保持到应用程序退出的时候,才能够被回收掉
GitHub源码链接:



本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(下)的更多相关文章
- 《Flask Web开发实战:入门、进阶与原理解析》 学习笔记
一个视图函数可以绑定多个 URL 为了让互联网上的人都可以访问,需要安装程序的服务器有公网ip 如果过度使用扩展,在不需要 的地方引人,那么相应也会导致代码不容易维护 ,应该尽量从实际需求出发,只在需 ...
- 2月送书福利:ASP.NET Core开发实战
大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...
- [ASP.NET Core开发实战]开篇词
前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...
- .NET Core开发实战(第11课:文件配置提供程序)--学习笔记
11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
- 2、SpringBoot接口Http协议开发实战8节课(1-6)
1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...
- [ASP.NET Core开发实战]基础篇03 中间件
什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...
- [ASP.NET Core开发实战]基础篇01 Startup
Startup,顾名思义,就是启动类,用于配置ASP.NET Core应用的服务和请求管道. Startup有两个主要作用: 通过ConfigureServices方法配置应用的服务.服务是一个提供应 ...
- 2、SpringBoot接口Http协议开发实战8节课(7-8)
7.SpringBoot2.x文件上传实战 简介:讲解HTML页面文件上传和后端处理实战 1.讲解springboot文件上传 MultipartFile file,源自SpringMVC 1)静态页 ...
- [ASP.NET Core开发实战]基础篇06 配置
配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...
随机推荐
- 第1篇 numpy 语法
import numpy as np A = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], ], dtype=int) # dtype指定数据类型int float p ...
- 修改elasticsearch默认索引返回数
1. 背景 (1) 客户反映es查询只能返回10000个数据,而需求时返回1.9W个数据,因此需要设置对应索引的默认返回数index.max_result_window (2) 给客户部署的服务以do ...
- AHB 局限性
AHB's problem SoC bus 架构 AXI is used more and more 频率200M使用AHB,频率再升高就使用AXI AHB的问题 AHB协议本身限制要求较高,比如co ...
- [转帖]linux下查看内存频率,内核函数,cpu频率
https://www.cnblogs.com/lovesKey/p/10900501.html 查看CPU: cat /proc/cpuinfo # 总核数 = 物理CPU个数 X 每颗物理CPU的 ...
- [转帖]如何查看Docker容器环境变量,如何向容器传递环境变量
https://www.cnblogs.com/larrydpk/p/13437535.html 1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 了解Docker容器的运行 ...
- [转帖]prometheus和node_exporter中的磁盘监控
https://www.ipcpu.com/2021/04/prometheus-node_exporter/ prometheus和node_exporter中的磁盘监控.md 对于磁盘问题,我们主 ...
- [转帖]谈谈对K8S CNI、CRI和CSI插件的理解
K8S的设计初衷就是支持可插拔架构,解决PaaS平台不好用.不能用.需要定制化等问题,K8S集成了插件.附加组件.服务和接口来扩展平台的核心功能.附加组件被定义为与环境的其他部分无缝集成的组件,提供类 ...
- MySQL数据库页存储结构学习与了解
MySQL数据库页存储结构学习与了解 背景 MySQL总是出现奇奇怪怪的问题. 想着自己能够学习与提高一下. 最近看了很多文档.关于MySQL数据库相关的. 想着总结和提炼一下, 希望能够给未来的工作 ...
- 银河麒麟(Ubuntu)无法上网问题的解决方法
最近部门借了几台银河麒麟的服务器. 因为有特殊用途, 不允许连接互联网,所以没办法只能搭建一个小的局域网进行处理. 但是发现在搭建过程中遇到了一些坑, 之前协助同事解决odoo问题时也遇到过, 当时本 ...
- 冷备份MySQL数据库并且使用Docker直接运行的操作过程
备份数据库 查看数据库的数据文件的位置 systemctl status mysqld 查看启动进程以及防水 /etc/my.conf 查看datadir 指向Mysql数据库的存储数据路径. 关闭数 ...