依赖囚禁(俘获)
发生条件:
一个短时间的组件被另一个长时间的组件所持有就会发生囚禁依赖。
Autofac不会阻止你创建被囚禁依赖,因为这是开发人员的责任,有时候因为囚禁的发生将会得到一个解析异常。
1. 如何避免囚禁依赖
避免囚禁依赖的一般准则是:
使用该服务的组件的生命周期要小于等于正在使用的服务的生命周期。
例如:
有一个Web应用,我们通过传入请求中的一些信息来决定连接到哪一个数据库。
你可能需要以下组件:
- 接受当前请求和数据库连接工厂的repository
- 类似
HttpContext
的 current request ,可以用于决定业务逻辑. - 一个数据库连接工厂( database connection factory ),接受一系列参数并且返回正确的数据库连接
在这个示例中,我们考虑以下应该为每个组件设定怎样的生命周期,而当前请求的上下文是一个很明显的上下文环境,我们可以将当前组件的生命周期设定为每个请求为同一实例(Instance Per Request)。
如果我们将repository
设定为“单例"模式,即SingleInstance
模式,那么这个实例将会缓存在应用的整个生命周期内,该请求上下文(request context)
会被传入repository
中,并在应用的整个生命周期中一直被repository
所持有,即使当次请求已经结束了,这时候repository就是使用该服务的组件,而HttpContext
就是正在使用的服务,repository
是长期存在的,但是它却一直持有更小生存周期的组件,这就发生了囚禁依赖。
如果你将repository也设定为Instance Per Request
模式,那么它现在和当前请求存在一样长的生命周期,它们将会被同时释放,就不存在囚禁。
再进一步,我们将repository设定为Instance Per Dependency
即每一次依赖就创建一个新实例,这样也是可以的,它的生命周期比当前请求还要短,也不会发生囚禁现象。
数据库连接工厂( database connection factory )思考过程与之类似,但也需要根据情况分析而选择不同生命周期模式,例如实例化数据库连接工厂比较耗费资源,或者你需要维护一些内部状态它才能正常的工作,这时候可能就需要使用单例模式了。
2. 应该由开发者决定是否可以接受依赖囚禁
我们在实际开发中,应该根据情况来决定是否可以接受依赖囚禁的发生。
例如你有一个缓存类(CacheClass),它被有意设置为仅在消费组件的生命周期内缓存内容,如果该组件是单例的,那么该组件可以用于整个程序的生命周期中存储东西,如果是Instance Per Request
模式,那么它只能存储单次Web请求的数据,在这种情况下选择单例模式更好,虽然发生了依赖囚禁现象,但是只要开发人员理解这样设置生存期的后果,这样也是可以接受的。
概括来说,我们应该有意的让囚禁现象发生。
个人博客原文地址:https://www.wukailiving.cn/autofac-zhong-de-yi-lai-qiu-jin-xian-xiang.html
转载请注明出处谢谢!