1.ServiceCollection(依赖注入的容器)

ServiceCollection:ICollection作为依赖注入的容器,它存在一个List用来存放所有的注入到容器中的类型

这里以注入单例模式执行过程为例为例:




springboot 抽象类怎么被调用 springboot抽象类可以依赖注入吗_应用程序

注入流程




springboot 抽象类怎么被调用 springboot抽象类可以依赖注入吗_ide_02

注入后的容器



2.ServiceDescriptor(注入服务描述器)

private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime){            this.Lifetime = lifetime;            this.ServiceType = serviceType;}//标准的注入public ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime) : this(serviceType, lifetime){            if (serviceType == null) {throw new ArgumentNullException("serviceType");}            if (implementationType == null) {throw new ArgumentNullException("implementationType"); }            this.ImplementationType = implementationType;}//Singleton模式public ServiceDescriptor(Type serviceType, object instance) : this(serviceType, ServiceLifetime.Singleton) {     //校验省略            this.ImplementationInstance = instance;}//工厂模式,通过ServiceProvider的Func注入public ServiceDescriptor(Type serviceType, Func factory, ServiceLifetime lifetime) : this(serviceType, lifetime) {//校验省略        this.ImplementationFactory = factory;}

3.ServiceProvider(实例化器)

var provider = services.BuildServiceProvider();




springboot 抽象类怎么被调用 springboot抽象类可以依赖注入吗_单例模式_03


以Transient实例化详细执行流程如下图:

var orderService = provider.GetService();


springboot 抽象类怎么被调用 springboot抽象类可以依赖注入吗_springboot 抽象类怎么被调用_04


Singleton,Scope,Transient三种模式下的产生对象实例的流程如下:


springboot 抽象类怎么被调用 springboot抽象类可以依赖注入吗_应用程序_05


4.IServiceScope

创建作用域,也就是创建子容器

单例模式是在Root容器下的,只能程序停止时释放,Transient模式,每次都会产生新的实例,所以两者应用不多。我们可以使用Scope的实例测试。

1.准备服务类 public interface IOrderService    {    }    public class DisposableOrderService : IOrderService, IDisposable    {        public void Dispose()        {            Console.WriteLine($"DisposableOrderService Disposed:{this.GetHashCode()}");        }    }2.注入为Scope    services.AddScoped();    3.1调用       [HttpGet]        public int Get(            [FromServices] IOrderService aaa,            [FromServices] IOrderService bbb,            [FromServices]IHostApplicationLifetime hostApplicationLifetime,             [FromQuery]bool stop = false)        {            return 1;        }                【结果,只会打印一次,被释放的信息,因为aaa,bbb是同一个实例】3.2 新建scope调用         [HttpGet]        public int Get(            [FromServices] IOrderService aaa,             [FromServices] IOrderService bb,            [FromServices]IHostApplicationLifetime hostApplicationLifetime,             [FromQuery]bool stop = false)        {            using (IServiceScope scope = HttpContext.RequestServices.CreateScope())            {                var service = scope.ServiceProvider.GetService();            }            return 1;        }                【结果,会打印两次,被释放的信息。因为在scope内,相当于创建了一个子容器,重新创建一个是实例】

5.容器使用注意事项

1.容器会管理释放自己创建的对象,所以我们不要手动创建对象,然后放入容器。如果实现了IDisable接口,容器会帮助我们管理生命周期,调用Dispose方法。

只有Singleton接口可以直接传入一个new 的对象,其他两个接口的工厂模式和类型注入的模式的效果时一样的1.创建的实例由容器控制释放service.AddSignleton();2.实例的生命周期不由容器控制释放service.AddSingleton(new OrderService()));

2.单例是注入到应用程序的根容器(Root)中,根容器是伴随整个应用程序存在的。如果使用根容器获取Transient对象,那么将会永远存在整个应用程序周期中,不会释放。所以不要在跟容器中获取Transient对象

//跟容器是存放单例模式的,如果通过根容器获取临时对象,临时对象是不会被释放的。ApplicationService就是根容器app.ApplicationService.GetService();

3.ServiceCollection支持一个接口多个实现同时注入。

4.如果是在整个类中使用的对象,可以使用构造函数注入,如果仅仅是某个方法使用,那么可以通过属性标签的方式注入[FromService]