跟我一起学.NetCore之依赖注入作用域和对象释放
前言
????上一小節(jié)簡(jiǎn)單闡述了依賴注入及Asp.NetCore中自帶依賴注入組件的常規(guī)用法,其中提到容器管控了自己創(chuàng)建對(duì)象的生命周期,包含了三種生命周期:Singleton、Scoped、Transient,?對(duì)于Singleton、Transient相對(duì)于Scoped來(lái)說(shuō)比較好理解,其實(shí)這里面有一個(gè)作用域的概念,也可以理解為根容器和子容器的范圍;上一小節(jié)中有一個(gè)例子中說(shuō)到,當(dāng)注入的生命周期為Scoped的時(shí),在同一個(gè)請(qǐng)求內(nèi),注入的對(duì)象都是同一個(gè),這里Asp.NetCore將每個(gè)請(qǐng)求作為了一個(gè)作用域,在此作用域內(nèi),生命周期為Scoped的對(duì)象就是同一個(gè);下面簡(jiǎn)單說(shuō)說(shuō)作用域和對(duì)象釋放的常規(guī)知識(shí)點(diǎn);
正文
????作用域這里可以理解為服務(wù)范圍,由IServiceScope承載,如其源代碼所示,每一個(gè)服務(wù)范圍內(nèi)都一個(gè)根容器,如下所示:
//// 摘要:// /// The System.IDisposable.Dispose method ends the scope lifetime. Once Dispose// /// is called, any scoped services that have been resolved from /// Microsoft.Extensions.DependencyInjection.IServiceScope.ServiceProvider// will be /// disposed. ///public interface IServiceScope : Object, IDisposable{//?IServiceProvider?即代表容器//// 摘要:// /// The System.IServiceProvider used to resolve dependencies from the scope.// ///IServiceProvider ServiceProvider{get;}}????每一個(gè)服務(wù)范圍內(nèi)可以通過(guò)自身IServiceProvider創(chuàng)建對(duì)應(yīng)的子作用域,而任何一個(gè)子作用域的IServiceProvider都有對(duì)根容器的引用,如下圖結(jié)構(gòu):
? ? 每一個(gè)IServiceProvider中都會(huì)將其創(chuàng)建的對(duì)象存入列表中,針對(duì)于繼承與IDisposable接口的類型對(duì)象會(huì)單獨(dú)存放在一個(gè)列表中,當(dāng)作用域IServiceScope對(duì)象的Dispose方法被調(diào)用時(shí),最終對(duì)應(yīng)IServicePorvider對(duì)應(yīng)的對(duì)象列表也會(huì)清空,針對(duì)于繼承與IDisposable類型的對(duì)象會(huì)調(diào)用其Dispose方法;最后導(dǎo)致對(duì)應(yīng)作用域下容器創(chuàng)建的對(duì)象成為垃圾對(duì)象,被GC給回收;
????在Asp.NetCore中,框架默認(rèn)將其分有根作用域(與引用程序同生命周期)和請(qǐng)求作用域(每一個(gè)請(qǐng)求一個(gè)作用域),通常也會(huì)稱其為根容器和請(qǐng)求容器,名稱分別為ApplicationServices和RequestServices,在程序中獲取方式如下:
????通過(guò)IApplicationBuilder對(duì)象可以獲取ApplicationServices
????通過(guò)HttpContext.RequestServices獲取RequestServices
????作用域簡(jiǎn)單舉例,在請(qǐng)求作用域下再創(chuàng)建子作用域,分別查看對(duì)應(yīng)不同生命周期對(duì)象是否一致,新建一個(gè)WebApi項(xiàng)目,針對(duì)三個(gè)生命周期添加了對(duì)應(yīng)文件,結(jié)構(gòu)如下:
????
對(duì)應(yīng)紅框內(nèi)的文件內(nèi)容如下:
???????細(xì)心的小伙伴可能會(huì)看到,每個(gè)實(shí)現(xiàn)類里面都繼承了IDisposable接口,這主要是后面顯示釋放用的,這里先不管;編輯好以上內(nèi)容之后就將其進(jìn)行注冊(cè),如下:
????接下來(lái)就是使用了,這里通過(guò)這Action中使用,在當(dāng)前的請(qǐng)求作用域下創(chuàng)建子作用域,對(duì)比每一個(gè)生命周期對(duì)象,如代碼所示:
????運(yùn)行,進(jìn)行請(qǐng)求,看打印結(jié)果:
????
????對(duì)于Singleton來(lái)說(shuō)始終不變,因?yàn)槠涫歉S根容器生命周期,引用程序退出才釋放;
????對(duì)于Scoped來(lái)說(shuō)只要在自己的作用域內(nèi)就是單例的;
????對(duì)于Transient來(lái)說(shuō)始終創(chuàng)建;
????以上一直在說(shuō)釋放,下面利用繼承IDisposable接口釋放時(shí)會(huì)調(diào)用對(duì)應(yīng)Dispoable方法的原理簡(jiǎn)單演示各個(gè)生命周期的釋放時(shí)機(jī);在Controller中增加幾個(gè)Action方法,如下:
????這里使用IHostApplicationLifetime中的StopApplication模擬關(guān)閉程序釋放單例下的對(duì)象;運(yùn)行看效果:
? ??使用坑:不要從根容器中獲取Transient生命周期的對(duì)象,因?yàn)橥ㄟ^(guò)根容器創(chuàng)建的對(duì)象不會(huì)回收,除非等到應(yīng)用程序退出,這樣會(huì)導(dǎo)致內(nèi)存泄露;如下演示:
????
新增Action方法:
運(yùn)行,發(fā)送請(qǐng)求看結(jié)果:
總結(jié)
????作用域及對(duì)象釋放就簡(jiǎn)單說(shuō)這么多,容器只管理自己創(chuàng)建出來(lái)的對(duì)象生命周期;下一節(jié)說(shuō)說(shuō)使用第三方組件擴(kuò)展依賴注入功能;
總結(jié)
以上是生活随笔為你收集整理的跟我一起学.NetCore之依赖注入作用域和对象释放的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 跟我一起学.NetCore之依赖注入
- 下一篇: 跟我一起学.NetCore之配置初体验