《我用段子讲.NET之依赖注入其二》

”随着我们将业务代码抽象化成接口和实现两部分,这也使得对象生命周期的统一管理成为可能。这就引发了第二个问题,.NET Core中的依赖注入框架。”

1

听到董哥这么说,作为一位仅有3年左右经验的开发者小木同学一脸错愕,虽然这句话的每个词他都认识,但连在一起却犹如听天书。

”董哥,你说的第一句话,我倒是刚刚已经听你说明白了。但这第二句话却完全搞不懂。主要有两个问题,第一,什么叫做对象生命周期,其次,怎么实现统一管理的?”

董哥莞尔一笑:”那你觉得.NET对象是如何创建和销毁的?”

小木同学对这个话题并不陌生,他说:”对象的创建,一般用new关键词来创建,对象的销毁则一般使用对象继承自IDisposable,并在析构函数中释放。不过析构函数这种用法都是我在网上看到的,实际上没用过,这就属于对象生命周期管理吧?”

董哥说:”是的。”

小木继续说:”那按这个说法,我感觉.NET中不用刻意维护对象生命周期,垃圾回收机制会回收超出生命周期的对象吧。 ”

“事实上虽然.NET虽然会通Gc管理对象生命周期,实际上依然会面临这样的问题。这有点像我们可能看不到地球的存在,但我们存在,那地球也是客观存在的,只是平时我们没注意观察而已。

那你们的代码里面,估计没刻意控制过对象的创建过程,而且估计也经常使用静态变量吧。”

“额,是啊,我司生产代码里面出现得最多的,估计就是new 对象的语句,以及定义为public static的静态变量了,有一次我认真的观察了一下,几乎每个类都会定义几个静态变量。”

听到小木这么说,董哥被逗乐了:“听起来有点搞笑,不过我也知道,你们这种HIS系统,本来就是业务非常复杂,如何快速的完成项目才最重要。“

2

董哥看到小木的杯子空了,又去给他加了一点水。

这时董哥窗外的湖面也掩映着一片夕阳的灿烂,微风吹过,粼粼波光,风景倒是挺雅致,不知不觉,已经临近6点半,他们围绕这个话题已经聊了快个把小时了,此时董哥他们办公室也迎来了下班高峰期,同事们渐次的离开办公室,但对技术爱好者来说,总是感觉不到时间流逝。

董哥回来后,把杯子递给小木,同时,也拿起自己的杯子喝了一口,他慢条斯理的说:

“在许多业务系统开发里面,内存仿佛不要钱,大不了就给医生们多加几根内存条,反正都是地方财政买单,也不会要开发人员出钱。再者,估计买内存条的钱,显然比优化代码付出的成本低,花那么多时间优化性能,有时确实反而付出了更高的时间成本。

而对于我们物联网嵌入式系统开发者来说,硬件基础设施都金贵着,有时稍微注意点,配置可能看起来差不多,但总价可以省出好几十块钱一台出来。如果生产量比较多,还能多赚不少钱。当然,并不是说.NET就不行,我们有的应用其实也在用.NET Core来开发,性能还挺不错的。“

小木也端起杯子喝了一口,回答道:

“也许只是我们公司是这样吧,估计那些大一点的公司会好许多。也有可能是.NET入门容易,没.NET Core那么多套路,所以很容易就放飞了。

那在.NET Core里面依赖注入框架是如何统一管理对象生命周期的?”

3

董哥继续拿起了那张画了一棵树的纸,他说:”不仅对象间的依赖关系本身像一棵树,对象的生命周期管理,其实也像这一棵树。首先是主程序不断的new对象,然后对象再不断的new子对象。就像主干长出枝干,枝干长出叶子,结构越来越复杂。但对象如果不断的堆积在内存中,就会引发内存泄漏(oom)问题,导致程序崩溃。你听过值对象和引用对象么?“

小木点了点头:“听说值对象放在栈上,引用对象放在堆上。”

“是的,当然,值对象在业务开发中可能用得没那么多,所以造成内存占用的,主要还是放在堆上的对象。垃圾回收策略倒是只有一句话,引用计数,分代回收,对象压缩。0代,1代,2代,大对象堆,分别有不同的回收策略。不过这些可能对你来说理解暂时有点困难,有机会再慢慢说。“

”比较容易理解的可能是,对象回收并非一直在发生,它只有在系统物理内存不足,达到内存回收阈值,手动调用GC.Collect方法等情况下发生。而且垃圾回收过程并非对程序毫无副作用,在某些性能要求特别高的场景,例如高并发场景下,发生计划外的垃圾回收,可能会导致程序偶发性变得卡顿,可能会造成用户体验度的下降。这也是痛点,也就是依赖注入框架所能解决的第二个问题。统一的生命周期管理“

董哥突然变得严肃起来。

“在.NET Core中,ASP.NET Core内置了依赖注入容器IServiceCollection和服务提供者IServiceProvider。对开发者来说,通过建立抽象,提取出接口或基类,再将该对象注册到依赖注入容器中。

在服务调用时,上层应用不再通过new的形式使用下层接口,而是在构造函数中,通过引入依赖注入框架实例化的下层实现,并由该框架来统一管理对象的生命周期。

这就是依赖注入框架所采取的手段。”

4

“听起来还是挺不错的,就是对开发者的操作习惯造成了一些影响。”木哥叹息道。

董哥点了点头,“对许多开发者来说,改变习惯如同断人财路。我也曾经见过很多开发者特别喜欢使用全局静态变量,仿佛不用静态变量就不会写代码了。事实上对专业开发者来说,出现的每一个静态变量都会让其产生很痛苦的感觉。

首先,全局静态变量由root根来进行管理的对象,除非应用程序退出,这些对象几乎不会释放。如果开发者再玩一些骚操作,例如用全局静态变量来存放集合,有时会成为gc的一场灾难片。

其次,全局静态变量就是单例对象,全局只会出现一次实例,并发访问时,很容易就会引发线程安全问题。线程安全问题看起来简单,实则是软件开发中最难处理的一类问题了。为了一劳永逸,有的开发者习惯于用lock语句来强制使之同步化,这又使得应用程序很难充分利用硬件性能带来的优势。

所以,开发者有时改变一些思维定势,例如尽量不要出现全局静态变量,如果一定要出现,也推荐使用依赖注入框架所提供的单例生命周期来管理,这样使得整个应用系统的生命周期管理都处于可控状态。当然,全局静态方法是允许存在的,类似于 public static string xxx这样的扩展方法,可以使开发者的代码变得非常优雅。

在我看来,定义接口通过依赖注入框架注册对象通过构造函数创建对象,看起来非常简单的三个步骤,却有可能使应用系统开发变得更加的高可控,仅就这么一个小小的变化,就已经显得.NET Core开发比传统.NET 开发更加的充满魅力和神奇。“

5

董哥一时激动,讲了许多在木哥看来有点完全搞不懂的概念。这也使得小木突然间一脸懵逼,不知道该如何接下这个话题,半响之后,他才逐渐吐出一个问题:”董哥,你说的单例生命周期是啥意思?我在.NET Core开发中好像隐约看到过,但有点不太理解它的含义,你能跟我简单讲一下么。“

董哥也意识到自己突然间聊嗨了,兀自的笑了一笑,然后说:“

在.NET Core提供的依赖注入框架中,提供了三种不同的生命周期。

第一种就是SingleTon单例生命周期,这种模式有点像设计模式中的单例模式,通俗而言,就是在软件的整个生命周期只会出现唯一一次实例,并随着应用程序的结束而销毁。他有点像全局静态变量,只是整个过程都由依赖注入框架管理。许多全局变量都可以通过该生命周期所提供的服务层维护。

第二种就是Scoped生命周期,用中文翻译有点像作用域,这个作用域如何理解呢,我们都知道,http请求实际上是以为会话的形式进行的,每个会话往往会有IIS宿主开辟独立的线程来进行支持,那么这个作用域大概就像是给每个会话开辟的独立线程。在这个线程的生命周期内,开发者都能从依赖注入框架中,便捷的引入适当的服务层来提供业务支持。

第三种则是Transient生命周期,瞬时生命周期。一瞬间就过去了,说明时间很快。当然,如果用一句佛经来形容,那就是

一刹那者为一念,二十念为一瞬,二十瞬为一弹指,二十弹指为一罗预,二十罗预为一须臾,一日夜有三十须臾。

这个一瞬间,大概是0.36秒,实际上程序执行可能比这快很多。程序语言目前还无法跟佛经对应起来,我们只能把它理解为,一次方法调用过程为瞬时。一般是那种需要随用随取的对象,主要是相对于Scoped而言的,在控制台应用中使用非常广泛。

.NET Core提供的这三种生命周期,看起来很简单,但有时候也比较容易就踩坑了,这就需要我们平时注意自己的使用习惯了。“

6

一晃围绕这个话题,他们已经聊了一个半小时,随着窗外夕阳的逐渐消逝,窗外初上的华灯也使两位大佬意识到时间不早了,于是,他们也离开了办公室。

--end

我用段子讲.NET之依赖注入其二的更多相关文章

  1. 我用段子讲.NET之依赖注入其一

    <我用段子讲.NET之依赖注入其一> 1) 西城的某个人工湖畔,湖水清澈见底,湖畔柳树成荫.人工湖往北,坐落着两幢写字楼,水晶大厦靠近地铁站,由于为了与湖面天际线保持一致,楼层只有26层高 ...

  2. 依赖注入及AOP简述(九)——单例和无状态Scope .

    三.依赖注入对象的Scope及其生命周期 在前面的章节我们讲到,依赖注入容器之所以能够区别于以往的ServiceLocator等容器,是在于其不但能够自动构建多层次的.完整的依赖关系图,并且可以管理依 ...

  3. 依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP) .

    四.依赖注入对象的行为增强(AOP) 前面讲到,依赖注入框架的最鲜明的特点就是能够提供受容器管理的依赖对象,并且可以对对象提供行为增强(AOP)功能,所以这一章我们来讨论有关AOP的话题. 1.    ...

  4. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

  5. angular2系列教程(八)In-memory web api、HTTP服务、依赖注入、Observable

    大家好,今天我们要讲是angular2的http功能模块,这个功能模块的代码不在angular2里面,需要我们另外引入: index.html <script src="lib/htt ...

  6. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  7. ABP(现代ASP.NET样板开发框架)系列之6、ABP依赖注入

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

  8. ABP源码分析六:依赖注入的实现

    ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(6)-Unity 依赖注入

    系列目录 前言 为了符合后面更新后的重构系统,文章于2016-11-1日重写 本节重构一下代码,采用IOC控制反转,也就是依赖注入 您可以访问http://unity.codeplex.com/rel ...

随机推荐

  1. linux基础之进阶命令二

    本节内容 基础命令二: 1.      alias:查看和设置别名(alias:别名) alias 'ren=ls -ld' \ren 可不取消别名,执行ren原本的命令 2.      unalia ...

  2. nvm、nrm、npm 安装和使用详解

    一.nvm的安装和使用   nvm全称Node Version Manager是 Nodejs 版本管理器,它让我们能方便的对 Nodejs 的版 本进行切换. nvm 的官方版本只支持 Linux ...

  3. SpringMVC Jackson 库解析 json 串属性名大小写自动转换问题

    问题描述 在项目开发中,当实体类和表中定义的某个字段为 RMBPrice,首字母是大写的,sql 查询出来的列名也是大写的 RMBPrice,但是使用 jquery 的 ajax 返回请求响应时却出错 ...

  4. 2.7循环_while

    循环 目标 程序的三大流程 while 循环基本使用 break 和 continue while 循环嵌套 01. 程序的三大流程 在程序开发中,一共有三种流程方式: 顺序 -- 从上向下,顺序执行 ...

  5. System Verilog MCDF(一)

  6. Python+Selenium - 窗口切换

    当有新窗口出现时,并要在新窗口操作,步骤: 1.产生新窗口 2.获取所有窗口的句柄:driver.window_handles 3.切换函数:driver.switch_to.window(新窗口句柄 ...

  7. 改进遗传算法之CHC算法简要介绍

    简要介绍: CHC算法是Eshelman于1991年提出的一种改进的遗传算法的缩称,第一个C代表跨世代精英选择(Cross generational elitist selection)策略, H代表 ...

  8. Linux 2 的 Windows 子系统上发布 CUDA

    Linux 2 的 Windows 子系统上发布 CUDA 为响应大众需求,微软 宣布 在 2020 年 5 月的 建造 大会上推出了 建造 ( WSL 2 ) – GPU 加速功能.这一特性为许多计 ...

  9. 基于Kaggle的图像分类(CIFAR-10)

    基于Kaggle的图像分类(CIFAR-10) Image Classification (CIFAR-10) on Kaggle 一直在使用Gluon's data package数据包直接获得张量 ...

  10. ARM系列处理器和架构

    从一只ARM到另一只ARM! ARM处理器和架构 当前可用的处理器 ARM1 ARM2 ARM3 ARM4和5 ARM6 ARM7 ARM8 强壮有力的ARM ARM9 ARM10 ARM架构 v1  ...