ASP.NET Core依賴註入系統學習教程:5.生命周期

来源:https://www.cnblogs.com/green-jcx/archive/2022/08/17/16594812.html
-Advertisement-
Play Games

在現實生活中,生命周期一詞往往代表著某些人或事物從生到死的過程,而在依賴註入框架中,生命周期中的“生與死”體現為服務實例的創建和釋放。實際上對於介紹依賴註入框架的生命周期而言,就是在介紹依賴註入容器採用什麼樣的方式創建和釋放服務實例。 多個容器之間的組織結構 在介紹生命周期之前,我們必須先對“多個容 ...


在現實生活中,生命周期一詞往往代表著某些人或事物從生到死的過程,而在依賴註入框架中,生命周期中的“生與死”體現為服務實例的創建和釋放。實際上對於介紹依賴註入框架的生命周期而言,就是在介紹依賴註入容器採用什麼樣的方式創建和釋放服務實例。

多個容器之間的組織結構

在介紹生命周期之前,我們必須先對“多個容器之間的組織結構”和“服務範圍”有一個基本的瞭解,因為某類生命周期模式的服務實例和“服務範圍”息息相關的,如果該模式的服務實例不在“服務範圍”進行使用,那麼就失去了使用該模式的意義。“你知道我說的是哪個模式嗎?”

在依賴註入框架中容器並不是作為一個單一化的結構存在。最開始會初始化一個根容器,我們可以利用根容器創建一個服務範圍,創建的服務範圍中就會包含一個容器,這種容器我們又稱為子容器。基於這種創建方式,我們必須清楚知道一點的是:除了根容器之外,所有的子容器都包含在一個服務範圍中。而對於每個服務範圍而言,它可以不斷向下延申創建更多服務範圍,從而獲得更多的子容器。以這種類似於“父子關係”不斷向下延申創建,最終從表示上來看多個容器的組織會形成一個樹形層次化的結構。

而對於上圖中這種樹形層次化的結構,僅僅是我們根據容器的創建形式主觀意識上的一種邏輯結構,並非是依賴註入框架中實際的容器層次結構。從各個容器對象的引用層面來看,服務範圍中的容器對象(子容器)並不需要知道自己的“父容器”是誰,它只在乎根容器對象在哪裡,所以每個子容器對象只會針對根容器對象進行引用,根據這種引用情況多個容器之間的組織結構如下圖所示。

在代碼中如果要創建一個子容器,首先需要獲取ServiceCollection對象,並調用該對象的BuildServiceProvider方法構建出根容器對象。然後使用IServiceProvider介面類型的根容器對象調用CreateScope擴展方法,該擴展方法會使用IServiceScopeFactory(服務範圍工廠)來創建一個IServiceScope類型的服務範圍對象,而這個服務範圍對象中的ServiceProvider屬性就是創建的子容器。代碼創建過程如下:

 1    static void Main(string[] args)
 2         {
 3             //服務註冊信息集合
 4             var serviceCollextion = new ServiceCollection();
 5 
 6             //構建根容器對象
 7             IServiceProvider rootProvider = serviceCollextion.BuildServiceProvider();
 8 
 9             //創建服務範圍
10             IServiceScope scope =  rootProvider.CreateScope();
11 
12             //獲取子容器對象
13             IServiceProvider subProvider = scope.ServiceProvider;  
14 
15         } // END Main()

在ASP.NET Core應用中根容器對象稱為ApplicationService,服務範圍中的子容器對象被稱為RequesetService。對於“服務範圍”的概念其實就相當於,客戶端向伺服器發送的一次HTTP請求範圍。在具體處理每個請求時,ASP.NET Core框架會利用註冊的一個中間件來針對當前請求創建一個代表服務範圍的IServiceScope對象,該服務範圍對象提供的容器對象RequesetService,將用來提供當前HTTP請求處理過程中所需的服務實例。當HTTP請求處理完成後,對應的服務範圍將會被終結,服務範圍其下的容器對象以及容器中的服務實例都會被變成垃圾對象待GC進行回收。


創建

基於“多個容器之間的組織結構”和“服務範圍”的概念,促成了依賴註入框架中服務實例的3種生命周期模式:

  1. Singleton(單例);
  2. Scoped(範圍);
  3. Transient(暫時);

接下來,我們首先根據這3種生命周期模式,在創建服務實例上的特點進行介紹。

Singleton:該模式的服務實例只會創建一次,保存在根容器中,並且由根容器提供。在多個同根的子容器中可以共同訪問,並且不同子容器對於同一類型的訪問,獲取的是根容器中同一個實例,相當於單例模式的對象。

Scoped:該模式的服務實例在同一個服務範圍的容器中只會創建一次,在不同的服務範圍的容器中會多次創建,不同服務範圍的容器保存各自創建的服務實例。在同一個服務範圍的容器中,訪問同一類型的實例都屬於同一個,相當於在服務範圍內的單例模式對象。該模式需要註意的是:如果使用根容器提供Scoped模式的服務實例,那麼Scoped模式將會變成為Singleton模式。

Transient:該模式的服務實例不會在容器中進行保存。所以容器對象每次提供時都會創建一個新的服務實例,有著“即用即建,用後即棄”的特點。

 


釋放

依賴註入框架中容器對服務實例的釋放與.NET Core中的垃圾回收機制並不是一回事,容器對服務實例的釋放僅僅針對的是實現了IDisposable介面的服務實例,具體的釋放操作實際上就是調用它們的Dispose方法,而不同的生命周期模式的服務實例在釋放上會有不同的策略。根據策略的釋放特點可以歸納為如下兩類。

Singleton:由於Singleton模式的服務實例是保存在根容器中,所以必須等到根容器對象被釋放之後,Singleton模式的服務實例才會進行釋放。

Scoped和Transient:由於這兩種模式可以由根容器或子容器所創建,所以這兩種模式的服務實例釋放時機取決於創建它們的容器。如果創建它們的是根容器,則根容器釋放時它們才會釋放。如果創建它們的是子容器,那麼子容器釋放時它們才會釋放。


存儲列表

依賴註入框架中的容器在對服務進行存儲時,會將其劃分為兩類:一類是用於存放已實例化服務的Realized Services列表,另一類是用於存放可釋放服務實例的Disposable Services列表。

 

Realized Services列表在對Singleton和Scoped服務實例的提供上具有復用性,Singleton和Scoped提供時,首先會判斷所屬容器的Realized Services列表中是否存在對應的服務實例,如果Realized Services列表中存在對應的服務實例,那麼就使用現有的服務實例進行提供。

如果Realized Services列表中不存在對應的服務實例,那麼容器則會創建新的服務實例,併在提供之前先將新的服務實例添加到所屬容器的Realized Services列表中。如果這個新創建的服務實例實現了IDisposable介面,那麼這個新創建的服務實例還會被添加到所屬容器的Disposable Services列表中。

對於Disposable Services列表需要強調的是,其中的存儲的服務並不是已經被釋放的,而是僅針對些實現了IDisposable介面的服務進行了添加。當容器對象被釋放的時候,它會從自身的Disposable Services列表中提取出這些服務,並調用它們的Dispose方法,以便作為垃圾對象待GC回收。

 

知識改變命運
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • IaaS之計算 1.1 IaaS概述 IaaS(Infrastructure as a Service )提供托管的 IT 基礎架構,供用戶調配處理能力、存儲、網路和其他基礎計算資源。IaaS 提供商運行並管理此基礎架構,用戶可以在此基礎架構上運行選擇的操作系統和應用程式軟體。 在雲平臺中還會涉及以 ...
  • 1、Jar 包 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.comp ...
  • 1、conftest.py介紹 conftest.py是pytest框架的一種固定寫法,把fixture或者自己定義的插件寫到這個文件里就會自動去調用。我們前面都是將fixture寫到測試用例文件里,在實際工作中更推薦寫到conftest.py文件中,這樣更加靈活,易維護。 2、conftest.p ...
  • 1.樹的基礎知識概述 樹狀圖是一種數據結構,它是由 n(n>=1)個有限結點組成一個具有層次關係的集合。把它叫做“樹”是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具有以下的特點:每個結點有零個或多個子結點;沒有父結點的結點稱為根結點;每一個非根結點有且只有一個父結點;除了根結點外 ...
  • “如果一個線程兩次調用start(),會出現什麼問題?” 如果這個問題出自阿裡p6崗位第一面的提問,你能回答出來嗎? 大家好,我是Mic,一個工作了14年的Java程式員。 關於這個問題,涉及到線程的生命周期,我把完整的回答整理到了15W字的面試文檔裡面大家可以私信我領取。 下麵來看看高手的回答。 ...
  • 作者:小牛呼嚕嚕 | https://xiaoniuhululu.com 電腦內功、JAVA底層、面試相關資料等更多精彩文章在公眾號「小牛呼嚕嚕 」 什麼是Java泛型 Java 泛型(generics)是 Jdk 5 中引入的一個新特性, 泛型提供了編譯時類型安全檢測機制, 該機制允許程式員在編 ...
  • JDK 9-17新功能30分鐘詳解-語法篇-var 介紹 JDK 10 JDK 10新增了新的關鍵字——var,官方文檔說作用是: Enhance the Java Language to extend type inference to declarations of local variable ...
  • Vue——​​兩分鐘概述 Vue 是一個JavaScript 框架。 在其最簡單的模式中,您可以簡單地將核心 Vue 腳本包含在您的應用程式中,然後開始構建您的組件。 除此之外,對於更複雜的應用程式,您可以使用 Vue 自己的 CLI 創建(並最終發佈)一個 Vue 項目。 與大多數其他 JavaS ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...