本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7603642.htmlhtml
一样的又是一个双11如期而至,淘宝/天猫实时数据显示,开场3分钟总交易额突破100亿元人民币,简直可怕!同时产生了新的支付峰值诞生:25.6万笔/秒,以及数据库处理峰值4200万次/秒,说这些不是再给某某打广告哈,只是感叹现在的技术和业务双向驱动所带来的巨大冲击力,完成了史上基本不可能的事情,相信这毫不是极限,由于中国女人的支付能力是木有上限一说的,开玩笑啦,哈哈哈,好了废话说了一通,趁着博主也完成剁手以后,而后赶忙回到了继续学习的旅途中......git
当看到这文章题目的时候,相信不少人都是感叹,怎么又是一个来说依赖注入,怎么又是autofac浅析之类的,因此咯,此文只是博主阅读文档和平时的经验整合,而后呐,懂的人或者熟悉的中高配玩家,就能够绕道了,╮(╯﹏╰)╭,其实博主以前的我的项目仍是公司项目都是采用 Unity 来做为 ioc 套件进行使用,使用过程也还算良好也是基本具有了一个ioc组件应该具备的价值,或许也是微软企业套件为数剩下来很少的好的组件了吧,可是无奈后期博主以为Unity在性能或者灵活性上面逐渐展现出来的欠缺性,相比于今儿咱们熟知的autofac而言就越显尴尬,固然两者的官方文档都还算字字走心还算详细,可是重要的一点就是autofac在社区的热度以及地位就比较高了,其次就是它的周边扩展也是至关多的支持,固然啦,从一个系统或者项目俯视来看,它或者谁都是系统组件的一个冰山一角,都是做为一个零件使用,可是咱们依然不能就此忽略其的地位,由于它算是在一个系统中处于贯穿的层次级别,因此在对象建立和依赖+生命周期统筹上面起到了决定性做用,因此各位同窗固然也得须要重点关注如何集成才是......github
首先按照国际惯例给出各自的wiki,Dependency Injection (DI) Wiki : https://en.wikipedia.org/wiki/Dependency_injection ;Inversion of control (IOC) Wike : https://en.wikipedia.org/wiki/Inversion_of_control ; 这里给出的是英文版解释,固然英语能保留原滋原味,不过我相信中文的解释更能让人接受一些,因此这里博主依然找出了中文相关的通俗解释,这里引用一篇好文当中的话(原文连接:http://www.cnblogs.com/liuhaorain/p/3747470.html);
一、依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。
二、控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。
三、依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。
四、IoC容器:依赖注入的框架,用来映射依赖,管理对象建立和生存周期(DI框架)。
至于每一个概念的解读到理解以及示例展现,就能够看上文给出的链接,文中的解析挺到位的,因此这里备份连接地址在文中惠存,文中有相关的通俗解释,能够加深影响后加以理解,内化之....web
固然也是由于 autofac 自己文档完备性,相信也是大部分玩家选择用它的缘由之一,简直感受加一块儿来就是一本薄的书了哈,因此这里博主前后阅读了两三遍之,采用了一遍蜻蜓点水有个印象,二遍择优而读加深理解,三遍查漏补缺,可能不少人都以为哪有这么麻烦,先用起来到时候有问题有不懂的地方再去翻查文档便可,当时候博主也是准备这样的来的,其实方式并无好坏一说,只是看我的喜爱和学习方法而已,博主打算在完成此框架的学习以后,就着手与案例分析和框架集成的工做了,其实先前早些时候已经尝试过了对通用开发框架的一些实践,不过如今看看有些愣之嫩之,因此在此对开发当中需求的框架基本过一遍以后心中有谱儿以后,再次作集成工做就会显得“稳”一些,上述是博主本身的想法......2333333数据库
看来都是经过一个主要对象ContainerBuilder
完成对各式各样的组件注册,且经过名字也能够知道此类是生成服务容器的生成器,在生成容器以前,天然就是注册各类相关组件或者服务啦,关于API注册相关的话,大体有如下相关主要方式注册,不限于此:
一、经过类型注册( Register by Type ),相似:builder.RegisterType
,同时这里当使用该注册件时,会经过反射实例化对象,且会选择最合适的构造函数使用会自动传递依赖项进去,固然官方也提供了builder.RegisterType
指定构造函数使用,这里最合适体如今该组件的依赖项在容器的是否存在而定。json
二、实例对象注册( Instance Components ),Demo代码所示:var output = new StringWriter();builder.RegisterInstance(output).As
, 其中方法 ExternallyOwned 能够忽略容器对 实例对象的释放控制,同时也能够注册 单例对象 使用,且须要注意注册单例实例对象释放应该由开发人员控制而不是容器 。性能优化
三、Lambda 表达式组件注册 ( Lambda Expression Components ),builder.Register(c => new A(c.Resolve()));
,其中表达式的灵活性和性能优化,是官方推荐的注册方式,分别体如今 利用表达式能够自定义解析依赖项和传递须要的构造函数( 也包含注册依赖的属性和根据参数自定义注册流程 )等等,其次就是表达式对于性能有必定的提高相对于反射而言。架构
四、泛型组件注册 (Open Generic Components):框架
builder.RegisterGeneric(typeof(NHibernateRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
这个即是咱们常用的API了,也就是咱们对仓储服务的注册,可是咱们实体有不少,因此这里就 须要泛型注册能够批量注入到容器中去,并且须要单独对某一个具体类型例如 NHibernateRepository
其余备注注意事项:
关于 组件与服务 的注意点:当一个组件以下注册为服务的时候 :
builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>();
若是 须要解析组件自己须要加上AsSelf() ,关键的 AsSelf 来表示,否则注册为服务会覆盖掉组件自己的注册结果。
默认注册状况下, 多个组件注册同一个接口,以最后一个为准,除非使用 Named 支持多组件同一个服务注册关系,且若是使用API:PreserveExistingDefaults ,能够是的第一个注册为默认项。
条件注册:主要API,OnlyIf 方法提供Lambda表达式表示指定条件下发生,IfNotRegistered 方法同理注定没注册条件下发生。
将 参数传递给组件做为注册需求 ,经过 表达式注册或者显示使用 WithParameter 方法传递便可,一样也能够在解析的传递参数也是能够的。
属性注册:经过表达式或者利用OnActivated事件来主动解析,若是注册的是反射组件须要使用 PropertiesAutowired 来突出属性的注入,一样提供了 WithProperty 来主动注入对应属性名的依赖项。
程序集扫描注册:RegisterAssemblyTypes 能够自定义扫描程序集逻辑指定类型注册,可使用 Except 排除不须要的类型,AsImplementedInterfaces 注册为类型对应的公开接口服务类型,RegisterAssemblyModules 注册自定义module,实现批量套件式注册,注意若是宿主程序使用iis,若是使用iis回收,触发程序集重载,须要使用 var assemblies = BuildManager.GetReferencedAssemblies().Cast
获取最新加载的程序集扫描
解析主要的方法即是 Resolve ,解析能够经过 NamedParameter 、TypedParameter 、ResolvedParameter 三种方式传递解析组件所须要的参数依赖,关于容器中的不一样关系类型的不一样解析方式有所不一样,具体参考:http://autofac.readthedocs.io/en/latest/resolve/relationships.html#supported-relationship-types,其实官方提供这么多重载或者API函数只是为了广大玩家的易用性,至于平时开发过程当中,使用的API数量相对来讲仍是有限的,那博主自身状况设定,直接依赖和延迟实例化对象用到过了,还有一点:关于可枚举对象服务组件的注册,也就是一个接口多个实现类,解析接口默认若是没有注册回抛出异常,可是以下方式则是为empty,scope.Resolve<IEnumerable
根据官方的说法,其中有两点是值得开发人员注意的:
一、生命周期范围是可嵌套的,它们控制组件如何共享。例如,单例服务可能从根生存期范围解决,而单个工做单元可能须要本身的其余服务实例,你能够经过在注册时设置其实例范围来肯定组件的共享方式。例如 UserService 须要 RoleRepository 须要它们的scope处于处于同一个层次
二、using scope会主动追踪范围内组件,并在释放范围内组件在scope结束的时候。例如,若是您有一个实现了IDisposable的组件,而且您能够从scope范围内解析出来,则该scope范围将为你处理该对象的释放工做,自动处理让使用者没必要知道底层实现。可是若是不须要自动管理,你能够控制此行为或添加新的处置行为。
始终从scope范围内解析服务而非根容器,这一点很重要。因为生命周期范围的跟踪特性,若是您从跟容器中解析了大量的一次性组件,则可能会无心中形成内存泄漏,由于根容器将持有对那些一次性组件的引用(一般是应用程序的生命周期)。若是Autofac检测到单例或共享组件的使用状况,它会自动将其放入适当的跟踪范围。因此上诉的状况,能够理解为尽可能使用自建scope来解析服务组件,而跟容器就应该注册相似单例服务,与容器和应用程序本属于一个生命周期的东西
官方例子很好地说明了,在一个web应用程序中应该如何分配组件注册的生命周期的选择问题:
如今应用程序具备一个全局单例日志记录服务,而后两个同时请求进入Web应用程序,每一个请求都是一个逻辑的“工做单元”,每一个请求都须要本身的订单处理服务,每一个订单处理服务都须要将信息记录到日志服务中。在这种状况下,拥有包含单例记录服务的根生存期范围,而且每一个请求都有一个子生命周期范围child scope,每一个范围都有本身的订单处理服务:
+---------------------------------------------------+ | Autofac Container | | Root Lifetime Scope | | | | Logging Service | | (shared across all requests) | | | | +----------------------+ +----------------------+ | | | First Request Scope | | Second Request Scope | | | | | | | | | | Order Processor | | Order Processor | | | +----------------------+ +----------------------+ | +---------------------------------------------------+
当每一个请求结束时,请求生存期范围结束,相应的订单处理器被释放(若是实现了IDisposable)。Log日志记录服务做为一个单例,在未来的请求中保持共享。
关于具体注册的时候可供选择的实例生命周期范围,默认状况下是使用的:InstancePerDependency 也就是瞬态,每次解析都是一个新的对象,SingleInstance 单例很少说,InstancePerLifetimeScope scope范围内共享实例,经过 BeginLifetimeScope 便可创建一个scope范围,InstancePerMatchingLifetimeScope 指定具体name的scope范围内实例对象共享,其中pre request scope就是利用这道理实现了每次请求一个独立的做用域,InstancePerRequest web应用单次请求组件单例,注意若是木有请求的环境下,解析组件会抛出异常,InstancePerOwned 基本用不到,Thread Scope 参照线程启动的时候构建InstancePerLifetimeScope类型的做用范围曲线救国就能够了
关于服务依赖致使各自依赖项长期存活问题,通常状况下,应用程序中,上层服务组件所须要依赖的下层服务的生命周期要小于等于上层服务的生命周期便可,这样就能够正确的表示依赖关系和隶属关系,可是得除开单例状况,由于它是贯穿了整个应用生命周期的存在。
关于组件对象的释放问题,通常的ioc容器包括autofac都已经实现了自动处理释放问题,根据不一样的注册生命周期选择,则会自动释放,不须要开发者关系,对象残留的问题。如须要手动释放其余自定义非托管资源能够利用 OnRelease event来自定义处理逻辑,注意这会覆盖base逻辑,因此若是自己组件实现了idisposable就要先调用base.Diposable()方法
这里博主仍是推荐代码注册,由于配置文件的管理也是挺麻烦的,除非须要再上线以后须要动态调整一下注册参数或者生命周期的选择等等,那就须要xml json等注册方式,通常状况不会自定注册源,且autofac module 的方法很好划分了大量组件分类注册的问题。
这里直接复制粘贴官方对每一个应用的demo代码便可,思路都是替换既有系统的默认的注册依赖组价,基本上已经足够咱们的使用,到时开发的时候直接参考sample便可
这里官方给出了最佳实践的一些开发方式或者注意点:http://autofac.readthedocs.io/en/latest/best-practices/index.html 我这里就不翻译,相信你们都看得懂
原本这篇水文在早些时候都应该要完成的,拖拖踏踏到如今,连广州都已经也到了冬天了,好冷......,还好有防寒服加持,至此,差很少主要博主想研究的框架都差很少了,至于说net core相关的也在偶尔持续关于 github issues 的动态,毕竟官方给了road map ,跪着也要实现不是嘛!接下来,博主就要基于实际应用开发集成各式组件,构建属于本身的单体应用架构,毕竟走向分布式的前提是,单体架构不够使用的状况下,固然后面设计的时候会相对引入一些ddd的相关思想,但并不是所有,由于要基于显示考虑问题才是嘛......未完待续!