<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      aspnetcore 中為什么向 ServiceCollection 中注入的 Class 可以做到 Singleton,Transient,Scoped,挺有意思,這篇就來聊一聊這一話題,自從 core 中有了 ServiceCollection, 再加上流行的 DDD 模式,相信很多朋友的項目中很少能看到 new 了,好歹 spring 十幾年前就是這么干的。

      二:Singleton,Transient,Scoped 基本用法

      分析源碼之前,我覺得有必要先介紹一下它們的玩法,為方便演示,我這里就新建一個 webapi 項目,定義一個 interface 和 concrete ,代碼如下:

      public class OrderService : IOrderService
          {
              private string guid;
              public OrderService()
              {
                  guid = $"時間:{DateTime.Now}, guid={ Guid.NewGuid()}";
              }
              public override string ToString()
              {
                  return guid;
              }
          }
          public interface IOrderService
          {
          }

      1. AddSingleton

      正如名字所示它可以在你的進程中保持著一個實例,也就是說僅有一次實例化,不信的話代碼演示一下哈。

       public class Startup
          {
              public void ConfigureServices(IServiceCollection services)
              {
                  services.AddControllers();
                  services.AddSingleton<IOrderService, OrderService>();
              }
          }
          [ApiController]
          [Route("[controller]")]
          public class WeatherForecastController : ControllerBase
          {
              IOrderService orderService1;
              IOrderService orderService2;
              public WeatherForecastController(IOrderService orderService1, IOrderService orderService2)
              {
                  this.orderService1 = orderService1;
                  this.orderService2 = orderService2;
              }
              [HttpGet]
              public string Get()
              {
                  Debug.WriteLine($"{this.orderService1}\r\n{this.orderService2} \r\n ------");
                  return "helloworld";
              }
          }

      接著運行起來多次刷新頁面,如下圖:

       可以看到,不管你怎么刷新頁面,guid都是一樣,說明確實是單例的。

      2. AddScoped

      正從名字所述:Scope 就是一個作用域,那在 webapi 或者 mvc 中作用域是多大呢? 對的,就是一個請求,當然請求會穿透 Presentation, Application, Repository 等等各層,在穿層的過程中肯定會有同一個類的多次注入,那這些多次注入在這個作用域下維持的就是單例,如下代碼所示:

       public void ConfigureServices(IServiceCollection services)
              {
                  services.AddControllers();
                  services.AddScoped<IOrderService, OrderService>();
              }

      運行起來多次刷新頁面,如下圖:

       很明顯的看到,每次刷 UI 的時候,guid都會變,而在同一個請求 (scope) 中 guid 是一樣的。

      3. AddTransient

      前面大家也看到了,要么作用域是整個進程,要么作用域是一個請求,而這里的 Transient 就沒有作用域概念了,注入一次 實例化一次,不信的話上代碼給你看唄。

       public void ConfigureServices(IServiceCollection services)
              {
                  services.AddControllers();
                  services.AddTransient<IOrderService, OrderService>();
              }

       從圖中可以看到,注入一次就 new 一次,非常簡單吧,當然了,各有各的應用場景。

      之前不清楚的朋友到現在應該也明白了這三種作用域,接下來繼續思考的一個問題就是,這種作用域是如何做到的呢? 要想回答這個問題,只能研究源代碼了。

      三:源碼分析

      aspnetcore 中的 IOC 容器是 ServiceCollection,你可以向 IOC 中注入不同作用域的類,最后生成 provider,如下代碼所示:

                  var services = new ServiceCollection();
                  services.AddSingleton<IOrderService, OrderService>();
                  var provider = services.BuildServiceProvider();

      1. AddSingleton 的作用域是如何實現的

      通常說到單例,大家第一反應就是 static,但是一般 ServiceCollection 中會有成百上千個 AddSingleton 類型,都是靜態變量是不可能的,既然不是 static,那就應該有一個緩存字典什么的,其實還真的有這么一個。

      1)RealizedServices 字典

      每一個 provider 內部都會有一個 叫做 RealizedServices 的字典,這個 字典 將會在后面充當緩存存在, 如下圖:

       從上圖中可以看到,初始化的時候這個字典什么都沒有,接下來執行 var orderService = provider.GetService<IOrderService>(); 效果如下圖:

        可以看到 RealizedServices 中已經有了一個 service 記錄了,接著往下執行 var orderService2 = provider.GetService<IOrderService>();,最終會進入到 CallSiteRuntimeResolver.VisitCache 方法判斷實例是否存在,如下圖:

       仔細看上面代碼的這句話: if (!resolvedServices.TryGetValue(callSite.Cache.Key, out obj)) 一旦字典存在就直接返回,否則就要執行 new 鏈路,也就是 this.VisitCallSiteMain。

      綜合來看,這就是為什么可以單例的原因,如果不明白可以拿 dnspy 仔細琢磨琢磨。。。

      2. AddTransient 源碼探究

      前面大家也看到了,provider 里面會有一個 DynamicServiceProviderEngine 引擎類,引擎類中用 字典緩存 來解決單例問題,可想而知,AddTransient 內部肯定是沒有字典邏輯的,到底是不是呢? 調試一下唄。

        和單例一樣,最終解析都是由 CallSiteRuntimeResolver 負責的,AddTransient 內部會走到 VisitDisposeCache 方法,而這里會一直走 this.VisitCallSiteMain(transientCallSite, context) 來進行 實例的 new 操作,還記得單例是怎么做的嗎? 它會在這個 VisitCallSiteMain 上包一層 resolvedServices 判斷,

       

      posted on 2023-01-27 10:47  小石頭的一天  閱讀(37)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品一区中文字幕| 这里只有精品在线播放| gogogo高清在线观看视频中文 | 亚洲欧美人成电影在线观看| 白银市| 日本亚洲一区二区精品久久| 91中文字幕一区在线| 女人高潮流白浆视频| 日韩精品18禁一区二区| 国产成人精品视频不卡| 日韩精品中文字幕无码一区| 性欧美vr高清极品| 精品人妻中文无码av在线| 亚洲人成人影院在线观看| 色狠狠色噜噜AV一区| 麻豆国产传媒精品视频| 亚洲精品成人一二三专区| 亚洲精品无码高潮喷水A| 99久久99久久久精品久久| 九九热视频在线观看一区| 国产一区二区三区小说| 成人国产av精品免费网| 最近2019中文字幕免费看| 人妻少妇精品无码专区| 两性午夜刺激性视频| 久久一级黄色大片免费观看| 日韩中文字幕人妻一区| 国产福利社区一区二区| 亚洲国模精品一区二区| 在线看国产精品自拍内射| 狠狠躁天天躁中文字幕无码| 亚洲一品道一区二区三区| 内射老阿姨1区2区3区4区| 国产老熟女一区二区三区| 国产迷姦播放在线观看| 野外做受三级视频| 国产玖玖视频| 久久成人国产精品免费软件| 精品国产午夜理论片不卡| 色欲综合久久中文字幕网| 色综合久久一区二区三区 |