Autofac容器对象实例的几种生命周期类型
实例范围决定了如何在同一服务的请求之间共享实例。 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况。
当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作用域)或某种上下文中的单个实例,例如 线程或HTTP请求(每个生命周期范围)。
这适用于从显式Resolve()
调用返回的实例以及容器内部创建的实例,以满足另一个组件的依赖关系。
选择正确的生命周期范围将有助于避免组件寿命过长或不够长的俘获依赖和其他陷阱。 开发人员需要为每个应用程序组件做出正确的选择。
1.Instance Per Dependency
每次都会返回一个新的实例,并且这是默认的生命周期。
var builder = new ContainerBuilder();
// This...
builder.RegisterType<Worker>();
// 此句代码的效果同上
builder.RegisterType<Worker>().InstancePerDependency();
当您解析每个依赖项的实例组件时,每次都会得到一个新组件。
using(var scope = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
// Every one of the 100 Worker instances
// resolved in this loop will be brand new.
var w = scope.Resolve<Worker>();
w.DoWork();
}
}
2.Single Instance
单例,所有服务请求都将会返回同一个实例。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().SingleInstance();
当您解析单个实例组件时,无论您请求何处,都始终获得相同的实例。
// It's generally not good to resolve things from the
// container directly, but for singleton demo purposes
// we do...
var root = container.Resolve<Worker>();
// We can resolve the worker from any level of nested
// lifetime scope, any number of times.
using(var scope1 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>();
// root, w1, and w2 are always literally the
// same object instance. It doesn't matter
// which lifetime scope it's resolved from
// or how many times.
}
}
}
3.Instance Per Lifetime Scope
在一个嵌套语句块中,只会返回一个实例。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerLifetimeScope();
在解决每个生命周期实例作用域组件时,每个嵌套作用域将获得一个实例(例如,每个工作单元)。
using(var scope1 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
// 每次从这里解析它
// 你会得到相同的实例。
var w1 = scope1.Resolve<Worker>();
}
}
using(var scope2 = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
//每次从这里解析它
//每次解析都会得到一个同样的实例,但是这个示例和上面的循环的实例不是同一个
var w2 = scope2.Resolve<Worker>();
}
}
4.Instance Per Matching Lifetime Scope
这与上面的'每个生命周期的实例范围'概念类似,但允许更精确地控制实例共享。
当您创建嵌套的生存期范围时,您可以“标记”或“命名”范围。具有每匹配生命周期范围的组件每个嵌套生命周期范围最多只有一个实例与给定名称匹配。这允许您创建一种“范围单例”,其中嵌套的生命周期范围可以在不声明全局共享实例的情况下共享某个组件的实例。
这对于特定于单个工作单元的对象是有用的,例如,一个HTTP请求,作为一个嵌套的生命周期可以创建每个工作单元。如果每个HTTP请求都创建一个嵌套的生命周期,那么每个具有每个生命周期范围的组件都将为每个HTTP请求创建一个实例。 (有关每个请求生命周期范围的更多信息。)
在大多数应用中,只有一层容器嵌套足以代表工作单元的范围。如果需要更多级别的嵌套(例如像global-> request-> transaction这样的东西),组件可以配置为使用标签在层次结构中的特定级别共享。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerMatchingLifetimeScope("myrequest");
提供的标记值在启动时与生存期范围关联。 如果在没有正确命名的生命周期范围时尝试解析每个匹配生命周期范围的组件,则会得到一个异常。
//使用标签创建生命周期
using(var scope1 = container.BeginLifetimeScope("myrequest"))
{
for(var i = 0; i < 100; i++)
{
var w1 = scope1.Resolve<Worker>();
using(var scope2 = scope1.BeginLifetimeScope())
{
var w2 = scope2.Resolve<Worker>();
// w1和w2始终是同一个对象
//实例,因为该组件是每个匹配生命周期范围的,
//所以它实际上是一个单例
//命名范围
}
}
}
//使用标签创建另一个生命周期作用域
using(var scope3 = container.BeginLifetimeScope("myrequest"))
{
for(var i = 0; i < 100; i++)
{
// w3 will be DIFFERENT than the worker resolved in the
// earlier tagged lifetime scope.
var w3 = scope3.Resolve<Worker>();
using(var scope4 = scope3.BeginLifetimeScope())
{
var w4 = scope4.Resolve<Worker>();
// w3和w4始终是同一个对象,因为
//他们在相同的标记范围内,但他们是
//与之前的w1,w2不一样。
}
}
}
//你无法解析每个匹配生命周期的组件
//如果没有匹配的范围。
using(var noTagScope = container.BeginLifetimeScope())
{
//因为这个范围没有,所以抛出一个异常
//有预期的标签,也没有任何父范围!
var fail = noTagScope.Resolve<Worker>();
}
5.Instance Per Request
某些应用程序类型自然适用于“请求”类型语义,例如ASP.NET Web Forms和MVC应用程序。 在这些应用程序类型中,有能力为每个请求提供一种“单例”。
通过提供众所周知的生命周期范围标记,注册便利方法以及针对常见应用程序类型的集成,每个请求的实例基于每个匹配生命周期范围的实例构建。 但在幕后,它仍然只是每个匹配生命周期范围的实例。
这意味着如果您尝试解析注册为每个请求实例但没有当前请求的组件,那么您将得到一个异常。
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerRequest();
6.Instance Per Owned
拥有的隐式关系类型创建新的嵌套生命周期作用域。 可以使用每个拥有实例的注册来将依赖关系限定到拥有的实例。
var builder = new ContainerBuilder();
builder.RegisterType<MessageHandler>();
builder.RegisterType<ServiceForHandler>().InstancePerOwned<MessageHandler>();
在这个例子中,ServiceForHandler
服务将被限制在拥有的MessageHandler
实例的生命周期中。
using(var scope = container.BeginLifetimeScope())
{
//消息处理程序本身以及
//解析依赖的ServiceForHandler服务
//在一个小小的生命周期范围内
// “范围。” 请注意解析一个拥有的<T>
//表示您负责处理。
var h1 = scope.Resolve<Owned<MessageHandler>>();
h1.Dispose();
}
原文:http://autofaccn.readthedocs.io/en/latest/lifetime/instance-scope.html
Autofac容器对象实例的几种生命周期类型的更多相关文章
- Autofac学习之三种生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency
InstancePerLifetimeScope:同一个Lifetime生成的对象是同一个实例 SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象:每次都用同一个对象: In ...
- Autofac学习之三种生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency 【转载】
InstancePerLifetimeScope:同一个Lifetime生成的对象是同一个实例 SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象:每次都用同一个对象: In ...
- Vue 实例详解与生命周期
Vue 实例详解与生命周期 Vue 的实例是 Vue 框架的入口,其实也就是前端的 ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进 ...
- Java对象在JVM中的生命周期
当你通过new语句创建一个java对象时,JVM就会为这个对象分配一块内存空间,只要这个对象被引用变量引用了,那么这个对象就会一直驻留在内存中,否则,它就会结束生命周期,JVM会在合适的时 ...
- JAVA-JSP内置对象之session对象设置并获得session生命周期
相关资料:<21天学通Java Web开发> session对象设置并获得session生命周期1.通过session对象的setMaxInactiveInterval()方法可以设置se ...
- ASP.NET Core :容器注入(二):生命周期作用域与对象释放
//瞬时生命周期 ServiceCollection services = new ServiceCollection(); services.AddTransient<TestServiceI ...
- spring总结之一(spring开发步骤、bean对象的管理、bean生命周期)
###spring 1.概念:开源,轻量级,简化开发的企业级框架. 开源:免费,发展快. 轻量级:占内存小. 简化开发:通用的功能封装,提高程序员的开发效率.--------------------- ...
- 05-Vue入门系列之Vue实例详解与生命周期
Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成.编译.挂着. ...
- 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期
一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...
随机推荐
- <自动化测试方案_3>第三章、怎么样实现自动化测试?(How)
第三章.怎么样实现自动化测试?(How) 自动化测试分为:代码单元自动化测试.API接口自动化测试.UI自动化测试 代码单元自动化测试,一般是无法做到的,因为项目的原因,代码单元是不做自动化,其测试是 ...
- 你不可不知的Java引用类型之——PhantomReference源码详解
定义 PhantomReference是虚引用,该引用不会影响不会影响对象的生命周期,也无法从虚引用中获取对象实例. 说明 源码介绍部分其实也没多大内容,主要内容都在前面介绍中说完了.PhantomR ...
- git 入门教程之本地仓库
本地仓库 背景 创建工作目录 平时工作时我们习惯对文档分门别类进行管理,.doc .txt 等文本类型的文件习惯存在 doc文件下,开发java js 等源代码文件存在在 src 目录下,这一点很好理 ...
- 【转】JSF中的三大核心组件 UI标签的详细介绍和使用举例
JSF提供了大量的UI标签来简化创建视图.这些UI标签类似于ASP.NET中的服务器组件.使用这些标签,可以通过其value,binding,action,actionListener等属性直接绑定到 ...
- java国际化---native2ascii.exe 的使用方法
从另一个博客迁移 native2ascii.exe使用方法: 命令的语法格式: native2ascii -[options] [inputfile [outputfile]] 说明: -[optio ...
- SQL Server基础之表级触发器
触发器分为两种,一种与数据表绑定,响应数据表指定动作(insert.delete或update),此处称为表级:一种与数据库本身绑定,响应数据定义语句(主要是CREATE.ALTER 和 DROP 开 ...
- hive笔记:转义字符的使用
hive中的转义符 Hadoop和Hive都是用UTF-8编码的,所以, 所有中文必须是UTF-8编码, 才能正常使用 备注:中文数据load到表里面, 如果字符集不同,很有可能全是乱码需要做转码的, ...
- Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)
1 非抢占式和可抢占式内核 为了简化问题,我使用嵌入式实时系统uC/OS作为例子 首先要指出的是,uC/OS只有内核态,没有用户态,这和Linux不一样 多任务系统中, 内核负责管理各个任务, 或者说 ...
- c/c++ 数组和指针
c/c++ 数组和指针 知识点 1,数组就是指针,对应代码里的test1 2,用auto声明,得到的是指针,对应代码里的test2 3,用decltype声明,得到的不是指针 ,对应代码里的test3 ...
- php学习----基本介绍及数据类型
php 官方手册:http://php.net/manual/zh/ 1.PHP(全称 Hypertext Preprocessor,超文本预处理器的字母缩写)是一种服务器端脚本语言,它可嵌入到 HT ...