Autofac 是一款超赞的 .NET IoC 容器 ,在众多性能测评中,它也是表现最优秀的一个。它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改。它的实现方式是将常规的.net类当做 组件 处理。

简单的性能测试

在 LINQPad 中,我们可以很容易的构建出一个测试环境(需要引入 Microsoft.Extensions.DependencyInjection 和 Autofac.Extensions.DependencyInjection 组件):

写一些简单的性能进行测试代码:

在 LINQPad 中对上述代码进行一万次、十万次、百万次三个量级的测试,得出以下报表(纵轴单位为“毫秒”):

从统计图中可以看到,即便是最耗时的 Transient 对象,百万级别创建的时间消耗也不到 400 毫秒。这说明,大多数情况下 Autofac 之类的 IoC 容器不会成为应用的性能瓶颈。

构造函数爆炸

当一个系统不断完善,业务在底层会被不断拆分为小的 Service ,然后在顶层(应用层或表现层)组装以完成功能。这表示在 Controller 中我们需要注入大量的 Service 才能保证功能完备。如果我们需要的对象通过构造函数注入,那么就会造成该构造函数的参数多到爆炸。

nopCommerce 是一个 ASP.NET 开发的电子商城系统,具备商城该有的各种功能和特性。在 ShoppingCartController 中你可以看到以下代码:

构造函数爆炸的性能问题

即便参数再多,在感官上也只是一个强迫症的问题。但构造函数爆炸所造成的影响不仅仅只是看上去没那么舒服而已。当我们注入一个对象时,IoC 容器会保证该对象以及其依赖的对象已经被正确初始化。所以我们不能简单的根据注入对象的数量来判断性能消耗,因为很有可能某个接口的实现依赖了数个其他对象。

当我们访问一个网页时,只会用到 Controller 中的某一个方法,通常,该方法不会对所有注入的对象都产生依赖。这也意味着我们创建了大量非必要的对象,为内存和 GC 造成了压力。

在 ASP.NET Core 中解决构造函数爆炸问题

ASP.NET Core 提供了一个名为 FromServicesAttribute 的属性来帮助解决必须在构造函数中注入依赖的问题。我们可以为 Action 的参数增加此属性,将所需的依赖注入进来:

这当然解决了构造函数爆炸的问题,很好。但同时,该方案也让方法的参数变得复杂也为单元测试留下了障碍,依旧不够完美。

使用 IServiceProvider 解决构造函数爆炸问题

在依赖注入容器中包含的所有对象都可以通过 IServiceProvider 获取到。基于该特性可以实现依赖对象的按需加载功能:

以上代码在 MyService 的构造函数中输出了创建日志。MyController 类型中通过 LazyGetRequiredService 方法实现了 MyService 的按需加载,构造函数也只剩下一个 IServiceProvider 对象。以上代码会产生下面的输出:

可以看到,在调用不依赖 MyService 的方法 NoCallMethod 时,MyService 并没有被创建。直到 CallMethod 被调用后用到了 MyService 时,它才被创建。

向 Volo.Abp 学习

Volo.Abp 在 4.2.0 版本中加入了一个新的接口: IAbpLazyServiceProvider 。

其实现同样采用 IServiceProvider 创建对象,同时使用了字典来保存对实例的引用。如果你和我一样使用 Abp 开发代码,那么 LazyServiceProvider 值得尝试。

.NET 中依赖注入组件 Autofac 的性能漫聊的更多相关文章

  1. 依赖注入组件 Autofac 的小记

    1.  批量给 Service 层自动注入.(支持 ASP.NET Core) builder.RegisterAssemblyTypes(typeof(IProductService).Assemb ...

  2. .NET Core 中依赖注入框架详解 Autofac

    本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...

  3. 【Unity】微软的一款依赖注入组件

    前言 前面学习了autofac这个依赖注入组件,本来是打算写在一起的,因为这个组件没打算像autofac一样详细的写,只是写下以前自己鼓捣玩搭建框架然后使用的一个依赖注入组件,并且也是进行了封装使用. ...

  4. .Net Core中依赖注入服务使用总结

    一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...

  5. ASP.NET MVC IOC依赖注入之Autofac系列(二)- WebForm当中应用

    上一章主要介绍了Autofac在MVC当中的具体应用,本章将继续简单的介绍下Autofac在普通的WebForm当中的使用. PS:目前本人还不知道WebForm页面的构造函数要如何注入,以下在Web ...

  6. ASP.NET MVC IOC依赖注入之Autofac系列(一)- MVC当中应用

    话不多说,直入主题看我们的解决方案结构: 分别对上面的工程进行简单的说明: 1.TianYa.DotNetShare.Model:为demo的实体层 2.TianYa.DotNetShare.Repo ...

  7. [Android]使用Dagger 2依赖注入 - 图表创建的性能(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5098943.html 使用Dagger 2依赖注入 - 图表创 ...

  8. 大比速:remoting、WCF(http)、WCF(tcp)、WCF(RESTful)、asp.net core(RESTful) .net core 控制台程序使用依赖注入(Autofac)

    大比速:remoting.WCF(http).WCF(tcp).WCF(RESTful).asp.net core(RESTful) 近来在考虑一个服务选型,dotnet提供了众多的远程服务形式.在只 ...

  9. 使用IDEA详解Spring中依赖注入的类型(上)

    使用IDEA详解Spring中依赖注入的类型(上) 在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件 ...

随机推荐

  1. 磁盘配额,通过ManagementClass("Win32_DiskQuota")

    C# using System; using System.Collections.Generic; using System.Management; namespace ConsoleApp2 { ...

  2. VNC使用及其常见问题解决方法

    博主之前在博文(https://www.cnblogs.com/kangbazi666/p/14153604.html)中已经介绍了多人VNC的配置方法,下面将简单介绍其使用方法及常见问题的解决方法. ...

  3. 云计算之3---OpenStack

    KVM管理平台 ​ KVM实现了虚拟化核心的监视工具,其在UI方便的管理工具多种多样.比较典型的管理工具有virsh,virt-manager,ovirt等. ​ virsh为命令行管理工具,功能强大 ...

  4. eclipse-切换分支-用途描述

    操作细节参考文章 https://www.cnblogs.com/sunrunzhi/p/6509448.html 分析切换分支的用途: 背景: 1. 项目开发使用分支1.分支2: 2. 分支1代码是 ...

  5. BCC和libbpf的转换

    BCC和libbpf的转换 本文讲述如何将基于BCC的BPF应用转换为libbpf + BPF CO-RE.BPF CO-RE可以参见上一篇博文. 为什么是libbpf和BPF CO-RE? 历史上, ...

  6. 漫画|web的主要安全问题

    在此主要说现在市面上存在的4个比较多的安全问题 一.钓鱼 钓鱼: 比较有诱惑性的标题 仿冒真实网站 骗取用户账号 骗取用户资料 二.篡改页面 有一大部分被黑的网站中会有关键字 (在被黑的网站中,用的最 ...

  7. element-ui使用后手记

    一.路由模式el-menu中使用路由模式 在el-meun中设置:router="true" 在el-menu-item中设置index="路由地址"

  8. (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇

    本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...

  9. Golang字符串是否存在于切片或数组中的小工具(基本等同于python in语法)

    // golang中是没有判断字符串是否存在数组或切片里的内置方法, 所以我们可以自己搞一个快速小组件 func Find(slice []string, val string) (int, bool ...

  10. MySQL中的这个池子,强的一批!

    Mysql 中数据是要落盘的,这点大家都知道.读写磁盘速度是很慢的,尤其和内存比起来更是没的说.但是,我们平时在执行 SQL 时,无论写操作还是读操作都能很快得到结果,并没有预想中的那么慢. 可能你会 ...