.NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(下)
06 | 作用域與對象釋放行為
接下來,把服務(wù)切換為單例模式,通過工廠的方式
services.AddSingleton<IOrderService>(p => new DisposableOrderService());啟動程序,輸出如下:
=======1========== =======2========== 接口請求處理結(jié)束可以看到代碼實(shí)際上不會被釋放
如果切換為瞬時模式,通過工廠的方式
services.AddTransient<IOrderService>(p => new DisposableOrderService());啟動程序,輸出如下:
=======1========== DisposableOrderService Disposed:12021664 DisposableOrderService Disposed:32106157 =======2========== 接口請求處理結(jié)束 DisposableOrderService Disposed:3165221 DisposableOrderService Disposed:13048313這里可以看到,獲取四個服務(wù)并且釋放掉
接下來把服務(wù)調(diào)整為自己創(chuàng)建,并注冊進(jìn)去
var service = new DisposableOrderService(); services.AddSingleton<IOrderService>(service);同樣我們也不會得到釋放的輸出
也就是說,通過這種方式注冊,容器不會管理對象的生命周期
如何識別這個區(qū)別呢?
在控制器中注入 IHostApplicationLifetime 接口
這個接口的作用是用來管理整個應(yīng)用程序的生命周期
它有一個方法 StopApplication
也就是說它可以把整個應(yīng)用程序關(guān)掉
接著,通過手工關(guān)掉的方式看一下應(yīng)用程序關(guān)閉時會不會把單例對象釋放掉
[HttpGet] public int Get([FromServices] IOrderService orderService,[FromServices] IOrderService orderService2,[FromServices]IHostApplicationLifetime hostApplicationLifetime,[FromQuery]bool stop = false) {Console.WriteLine("=======1==========");// HttpContext.RequestServices// 是當(dāng)前請求的一個根容器// 應(yīng)用程序根容器的一個子容器// 每個請求會創(chuàng)建一個容器using (IServiceScope scope = HttpContext.RequestServices.CreateScope()){// 在這個子容器下面再創(chuàng)建一個子容器來獲取服務(wù)var service = scope.ServiceProvider.GetService<IOrderService>();var service2 = scope.ServiceProvider.GetService<IOrderService>();}Console.WriteLine("=======2==========");if (stop){hostApplicationLifetime.StopApplication();}Console.WriteLine("接口請求處理結(jié)束");return 1; }首先用自己創(chuàng)建對象的方式
var service = new DisposableOrderService(); services.AddSingleton<IOrderService>(service);啟動程序
輸入 ?stop=true
https://localhost:5001/weatherforecast?stop=true輸出如下:
... DependencyInjectionScopeAndDisposableDemo.exe (進(jìn)程 16884)已退出,代碼為 0。 要在調(diào)試停止時自動關(guān)閉控制臺,請啟用“工具”->“選項(xiàng)”->“調(diào)試”->“調(diào)試停止時自動關(guān)閉控制臺”。 按任意鍵關(guān)閉此窗口. . .如果單例由容器來管理,切換回普通注冊方式
services.AddSingleton<IOrderService, DisposableOrderService>();啟動程序
輸入 ?stop=true
https://localhost:5001/weatherforecast?stop=true輸出如下:
Application is shutting down... 接口請求處理結(jié)束 DisposableOrderService Disposed:23399238對象釋放,應(yīng)用程序退出
這里說明單例的服務(wù)都是注冊在根容器里面
根容器的釋放意味著需要在整個應(yīng)用程序退出時釋放
這個時候它會釋放自己所管理的所有的 IDisposable 的對象
這里面有一個非常需要注意的坑:
假如把服務(wù)注冊成瞬時的
services.AddTransient<IOrderService, DisposableOrderService>();然后又在根容器里面去獲取這個對象
var s = app.ApplicationServices.GetService<IOrderService>();這意味著在根容器去持續(xù)的創(chuàng)建 IOrderService,但是由于根容器只會在應(yīng)用程序整個退出時回收,也就意味著這些對象會一直積累在應(yīng)用程序內(nèi)
調(diào)整控制器,不獲取 IOrderService
[HttpGet] public int Get([FromServices]IHostApplicationLifetime hostApplicationLifetime,[FromQuery]bool stop = false) {if (stop){hostApplicationLifetime.StopApplication();}return 1; }僅僅在根容器獲取一次
var s = app.ApplicationServices.GetService<IOrderService>();這樣運(yùn)行起來,每次請求(點(diǎn)擊刷新)的話,整個輸出是不會有內(nèi)容的,因?yàn)槲覀儧]有在子容器里面去獲取對象
但實(shí)際上當(dāng)我們退出的時候,會發(fā)現(xiàn)確實(shí)有一個實(shí)例被釋放掉了
DisposableOrderService Disposed:7511460也就是說,實(shí)現(xiàn)了 IDisposable 接口的服務(wù),如果時注冊瞬時的,又在根容器去做操作,它會一直保持到應(yīng)用程序退出的時候,才能夠被回收掉
總結(jié)
以上是生活随笔為你收集整理的.NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 管理学定律--彼得原理
- 下一篇: 使用BeetleX构建基础的SSL网络通