In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
Today, I will talk to you about how the scope of Singleton,Transient,Scoped is realized, which may not be well understood by many people. In order to make you understand better, the editor has summarized the following contents for you. I hope you can gain something according to this article.
One: background 1. Tell a story
A few days ago, a friend asked me to have time to analyze why the Class injected into ServiceCollection in aspnetcore can achieve Singleton,Transient,Scoped. This article will talk about this topic. Since there is ServiceCollection in core, coupled with the popular DDD model, I believe that many friends rarely see new in their projects, at least spring did it more than a decade ago.
Second: the basic usage of Singleton,Transient,Scoped
Before analyzing the source code, I think it is necessary to introduce how to play them. To facilitate the demonstration, I will create a new webapi project and define an interface and concrete as follows:
Public class OrderService: IOrderService {private string guid; public OrderService () {guid= $"time: {DateTime.Now}, guid= {Guid.NewGuid ()}";} public override string ToString () {return guid;}} public interface IOrderService {} 1. AddSingleton
As the name suggests, it can maintain an instance in your process, that is to say, it can be instantiated only once. If you don't believe it, show me the code.
Public class Startup {public void ConfigureServices (IServiceCollection services) {services.AddControllers (); services.AddSingleton ();}} [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";}}
Then run and refresh the page several times, as shown in the following figure:
As you can see, no matter how you refresh the page, guid is the same, indicating that it is indeed a singleton.
2. AddScoped
As the name suggests: Scope is a scope, so how big is the scope in webapi or mvc? Yes, it is a request. Of course, the request will penetrate the Presentation, Application, Repository and other layers. In the process of passing through the layer, there must be multiple injections of the same class. Then these multiple injections are maintained in this scope as a singleton, as shown in the following code:
Public void ConfigureServices (IServiceCollection services) {services.AddControllers (); services.AddScoped ();}
Run and refresh the page several times, as shown below:
It is obvious that every time you browse UI, the guid changes, but the guid is the same in the same scope.
3. AddTransient
As you have seen earlier, either the scope is the whole process or the scope is a request, but the Transient here does not have the concept of scope. Instantiate it once at a time, and if you don't believe it, I'll show you the code.
Public void ConfigureServices (IServiceCollection services) {services.AddControllers (); services.AddTransient ();}
As you can see from the figure, new is injected once, which is very simple, of course, each has its own application scenario.
Friends who were not clear before should have understood these three scopes by now, and the next question to think about is, how does this scope work? To answer this question, you have to study the source code.
Three: source code analysis
The IOC container in aspnetcore is ServiceCollection. You can inject classes with different scopes into IOC, and finally generate provider, as shown in the following code:
Var services = new ServiceCollection (); services.AddSingleton (); var provider = services.BuildServiceProvider (); 1. How the scope of AddSingleton is realized
Usually when it comes to singletons, our first reaction is static, but generally there are hundreds or thousands of AddSingleton types in ServiceCollection, all of which are static variables. Since it is not static, there should be a cache dictionary or something. In fact, there is such a dictionary.
1) RealizedServices Dictionary
Inside each provider, there will be a dictionary called RealizedServices, which will act as a cache presence later, as shown in the following figure:
As you can see from the image above, there is nothing in this dictionary during initialization, and then execute var orderService = provider.GetService (). The effect is as follows:
You can see that there is already a service record in RealizedServices, then execute var orderService2 = provider.GetService ();, and finally enter the CallSiteRuntimeResolver.VisitCache method to determine whether the instance exists, as shown in the following figure:
Take a closer look at the sentence in the above code: if (! resolvedServices.TryGetValue (callSite.Cache.Key, out obj)) returns directly as soon as the dictionary exists, otherwise it will execute the new link, that is, this.VisitCallSiteMain.
All in all, this is why you can have a single case. If you don't understand, you can think about it carefully with dnspy.
2. Explore the source code of AddTransient
As you can see earlier, there is a DynamicServiceProviderEngine engine class in provider, and dictionary cache is used in engine class to solve singleton problems. It is conceivable that there is no dictionary logic inside AddTransient, is it or not? Just debug it.
Like the singleton, CallSiteRuntimeResolver is responsible for the final parsing, and the internal AddTransient will go to the VisitDisposeCache method, and here we will go all the way to this.VisitCallSiteMain (transientCallSite, context) to do the new operation of the instance. Remember how the singleton did it? It will wrap a layer of resolvedServices judgment on this VisitCallSiteMain. Continue to track down the VisitCallSiteMain method, which will eventually call your constructor through the CallSiteKind.Constructor branch, as follows:
Protected virtual TResult VisitCallSiteMain (ServiceCallSite callSite, TArgument argument) {switch (callSite.Kind) {case CallSiteKind.Factory: return this.VisitFactory ((FactoryCallSite) callSite, argument) Case CallSiteKind.Constructor: return this.VisitConstructor ((ConstructorCallSite) callSite, argument); case CallSiteKind.Constant: return this.VisitConstant ((ConstantCallSite) callSite, argument) Case CallSiteKind.IEnumerable: return this.VisitIEnumerable ((IEnumerableCallSite) callSite, argument); case CallSiteKind.ServiceProvider: return this.VisitServiceProvider ((ServiceProviderCallSite) callSite, argument) Case CallSiteKind.ServiceScopeFactory: return this.VisitServiceScopeFactory ((ServiceScopeFactoryCallSite) callSite, argument);} throw new NotSupportedException (string.Format ("Call site type {0} is not supported", callSite.GetType ());}
In the end, VisitConstructor calls the constructor of my example code, so you should understand why you new every injection. As shown below:
3. Explore the source code of AddScoped
When you understand the principle of AddSingleton, AddTransient, I think Scoped is also very easy to understand. It must be a scoped and a RealizedServices, right? if you don't believe it, continue with the code.
Static void Main (string [] args) {var services = new ServiceCollection (); services.AddScoped (); var provider = services.BuildServiceProvider (); var scoped1 = provider.CreateScope (); var scoped2 = provider.CreateScope (); while (true) {var orderService = scoped1.ServiceProvider.GetService () Var orderService2 = scoped2.ServiceProvider.GetService (); Console.WriteLine (orderService); Thread.Sleep (1000);}}
Then check to see if both scoped1 and scoped2 have separate cache dictionaries.
As you can see from the figure, the ResolvedServices in scoped1 and scoped2 has an unused count, which means that the two exist independently and do not affect each other.
After reading the above, do you have any further understanding of how the scope of Singleton,Transient,Scoped is implemented? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.