默认范围绑定是否优先于无状态对象的Singleton绑定?

时间:2015-11-04 08:44:25

标签: dependency-injection guice

根据Guice wiki page,对于无状态对象,未编码绑定优先于Singleton。

我不同意该陈述,因为:

  1. Singleton范围为开发人员提供了更多信息。开发人员可以假设单个对象是线程安全的,并且可以在大多数时间不使用Provider的情况下注入它们。
  2. 由于与其他未编组对象的依赖关系,创建一个未编组的对象可能很昂贵。
  3. 无范围对象的循环依赖只能通过Providers解决,这可能会导致奇怪的行为。 例如A依赖于B,B依赖于Provider,并且A中的某个方法f()调用B调用A中的某个方法,然后每次调用f()时都会创建A和B的新实例。
  4. 将Request Scoped对象注入未编组的对象时,很难判断您是否需要提供者,因为未编码对象的生命周期未知。
  5. 有人可以解释为什么默认范围是首选的无状态对象的单例范围?

1 个答案:

答案 0 :(得分:1)

对于未编码对象而不是单例对象的偏好有一个重要而重要的原因:单例对象永远不会被垃圾收集,它们所持有的对象的整个传递树也不能被引用。< / em>它们的结构需要同步(以防止在创建过程中出现竞争条件),然后它们会在注射器的整个生命周期内保留在内存中。

这尤其是一个问题,因为在生产环境中,all Guice singletons are eager无论是否绑定asEagerSingleton。这意味着在生产中,单个树的内存承诺在创建注入器时开始,并且通常持续到应用程序关闭。

单独使用Singletons可能会导致启动速度变慢,内存需求量大于明智地选择单例。

当然,如果对象及其依赖项都是无状态的,那么每个对象的内存占用量都很小。但是,如果您的单例依赖于依赖于依赖于数据库的对象的对象,则在启动时将需要该数据库及其内存,并且永远不会释放。

injector ___________________TIME_________________________\
creation                                                 /

|---------------------SINGLETON-------------------------->
   |----------REQUEST A------------|   |---REQUEST B----->
      |-UNSCOPED C-| |-UNSCOPED D-|      |-UNSCOPED E-|

范围大致跟踪对象的生命周期,目标是避免将较窄范围的对象注入更宽范围的对象(例如,保留未绑定的对象C,这可能是与请求A相关但不是请求B)。这样做将是范围扩大注入

当您提到未穿眼镜的物体时,请将它们视为短暂的或一次性的,并尽可能缩小范围。这使得无状态对象变得特别容易,因为你拥有的实例并不重要。

这些未编组对象也可以在不使用提供程序的情况下自由地在图中注入任何对象,前提是未绑定对象与您选择的任何其他依赖项相比总是具有更短的生命周期。相比之下,单身人士必须使用提供者来处理所有非单身依赖关系,因为它绝对会比它所依赖的任何非单身人士更长久。

这应该在您需要提供商时明确说明,正如您在上面的#1和#4中所提到的那样。

总之,我只能将你引回the section you linked:除非你有充分的理由(州,昂贵的建筑或资源管理),否则你应该让你的注射器不受约束。