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. Blogs实现导航菜单

    #1.隐藏默认导航菜单 #header{display:none;} /*在页面定制CSS里面最前面添加如下代码,最好添加在最前面*/ #2.添加页首html代码 <!-- 添加博客导航栏信息开 ...

  2. 【程序包管理】篇章2:rpm程序包来源合法和完整性验正

    来源合法性验正: 数字签名   私钥签名完整性    哈希 注意: 1.如果是网站下载的程序包的话,没有公钥,就无法进行来源合法性验证,所以最好使用系统自带的rpm程序包或去可靠的网站下载程序包.[如 ...

  3. [EF] - Code First处理Clustered Index

    Clustered Index <=>集群索引: http://msdn.microsoft.com/en-us/library/ms177443.aspx 由于其特殊性,使得每个tabl ...

  4. spark 系列之一 RDD的使用

    spark中常用的两种数据类型,一个是RDD,一个是DataFrame,本篇主要介绍RDD的一些应用场景见代码本代码的应用场景是在spark本地调试(windows环境) /** * 创建 spark ...

  5. 深度学习论文翻译解析(十六):Squeeze-and-Excitation Networks

    论文标题:Squeeze-and-Excitation Networks 论文作者:Jie Hu  Li Shen Gang Sun 论文地址:https://openaccess.thecvf.co ...

  6. react状态管理器之mobx

    react有几种状态管理器,今天先来整理一下mobx状态管理器,首先了解一下什么是mobx 1.mobx成员: observable action 可以干嘛: MobX 的理念是通过观察者模式对数据做 ...

  7. Docker容器技术--自定义网桥后的默认网卡名称

    新建docker虚拟网络命令 这里以172.18.0.1为例,名字为clusterdocker network create --subnet=172.18.0.0/16 cluster 当我们想新建 ...

  8. matplotlib中subplots的用法

    1.matplotlib中如果只画一张图的话,可以直接用pyplot,一般的做法是: import matplotlib.pyplot as plt plt.figure(figsize=(20,8) ...

  9. spark进行相同列的join时,只留下A与B关系,不要B与A

    一.问题需求: 近期需要做一个商品集合的相关性计算,需要将所有商品进行两两组合笛卡尔积,但spark自带的笛卡尔积会造成过多重复,而且增加join量 假如商品集合里面有: aa   aa bb   b ...

  10. spark:reducebykey与groupbykey的区别

    从源码看: reduceBykey与groupbykey: 都调用函数combineByKeyWithClassTag[V]((v: V) => v, func, func, partition ...