• .NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(上)


    06 | 作用域与对象释放行为

    作用域主要由 IServiceScope 这个接口来承载

    对于实现 IDisposable 类的实例的对象,容器会负责对其生命周期进行管理,使用完毕之后,他会释放这些对象

    实现 IDisposable 接口类型的释放:

    • 1、容器只会负责由其创建的对象,如果这个对象是自己创建出来并放到容器里的,容器不负责释放这个对象
    • 2、在容器和子容器释放时,容器才会去释放这些对象,也就是说容器的生命周期与其创建的对象的生命周期是有对应关系的

    两点建议:

    • 1、在根容器,最好不要创建实现了 IDisposable 瞬时服务
    • 2、避免手动创建实现了 IDisposable 对象,然后塞到容器里面,应该尽可能地使用容器来管理我们对象的创建和释放

    演示代码:
    https://github.com/witskeeper/geektime/tree/master/samples/DependencyInjectionScopeAndDisposableDemo

    先看一下服务

    namespace DependencyInjectionScopeAndDisposableDemo.Services
    {
    
        public interface IOrderService
        {
    
        }
    
        public class DisposableOrderService : IOrderService, IDisposable
        {
            public void Dispose()
            {
                Console.WriteLine($"DisposableOrderService Disposed:{this.GetHashCode()}");
            }
        }
    }
    

    首先定义 IOrderService

    接着定义 IOrderService 的实现 DisposableOrderService,并实现了 IDisposable 这个接口

    在释放的时候打印释放信息,并输出对象的 HashCode

    接着是服务注册(Startup)

    services.AddTransient<IOrderService,DisposableOrderService>();
    

    这里先注册一个瞬时服务,将 IOrderService 注册进去

    然后看一下控制器(WeatherForecastController)

    [HttpGet]
    public int Get([FromServices] IOrderService orderService,
        [FromServices] IOrderService orderService2)
    {
        return 1;
    }
    

    这里 FromServices 获取了两次 IOrderService

    这里不需要写任何代码对它进行操作,因为整个生命周期是由容器去管理的

    启动程序,输出如下:

    DisposableOrderService Disposed:10579059
    DisposableOrderService Disposed:47945396
    

    可以看出,执行完毕之后,DisposableOrderService 会被释放掉,并且两个对象都会被释放掉

    两个对象的 HashCode 不同

    瞬时服务在每一次获取的时候都会获得一个新的对象

    接着,添加一行代码表示服务

    [HttpGet]
    public int Get([FromServices] IOrderService orderService,
        [FromServices] IOrderService orderService2)
    {
        Console.WriteLine("接口请求处理结束");
        return 1;
    }
    

    输出一下,表示我们的接口已经访问完毕,看一下释放时机在哪里

    启动程序,输出如下:

    接口请求处理结束
    DisposableOrderService Disposed:35023218
    DisposableOrderService Disposed:13943705
    

    由此看出,接口请求处理结束后,才释放对象

    接下来看一下 Scoped 模式

    服务注册

    services.AddScoped<IOrderService>(p => new DisposableOrderService());
    

    控制器

    [HttpGet]
    public int Get([FromServices] IOrderService orderService,
        [FromServices] IOrderService orderService2)
    {
        Console.WriteLine("=======1==========");
        // HttpContext.RequestServices
        // 是当前请求的一个根容器
        // 应用程序根容器的一个子容器
        // 每个请求会创建一个容器
        using (IServiceScope scope = HttpContext.RequestServices.CreateScope())
        {
            // 在这个子容器下面再创建一个子容器来获取服务
            var service = scope.ServiceProvider.GetService<IOrderService>();
        }
        Console.WriteLine("=======2==========");
    
        Console.WriteLine("接口请求处理结束");
    
        return 1;
    }
    

    启动程序,输出如下:

    =======1==========
    DisposableOrderService Disposed:31307802
    =======2==========
    接口请求处理结束
    DisposableOrderService Disposed:31614998
    

    每次请求会获得两个释放,意味着每创建一个 Scoped 的作用域,每个作用域内可以是单例的

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    rsync命令使用方法
    Mysql(MyISAM和InnoDB)及Btree和索引优化
    初级java程序员-各公司技能要求
    Redis学习笔记二 (BitMap算法分析与BitCount语法)
    HTTP、TCP、IP协议常见面试题
    Redis学习笔记一(Redis的详细安装及Linux环境变量配置和启动)
    java-部分精选面试题
    Python基础-TypeError:takes 2 positional arguments but 3 were given
    Python3.7中urllib.urlopen 报错问题
    几道关于springboot、springCloud的面试题。
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/12339892.html
Copyright © 2020-2023  润新知