Dependency injection 对于无状态对象,默认作用域绑定优先于单例绑定吗?

Dependency injection 对于无状态对象,默认作用域绑定优先于单例绑定吗?,dependency-injection,guice,Dependency Injection,Guice,根据,对于无状态对象,无范围绑定优于单例绑定 但我不同意这一说法,因为: Singleton范围为开发人员提供了更多信息。开发人员可以假设单例对象是线程安全的,并且可以在大多数情况下在不使用提供程序的情况下注入它们 由于与其他非作用域对象的依赖关系,创建非作用域对象的成本可能会很高 非作用域对象的循环依赖只能通过提供程序来解决,这可能导致奇怪的行为。 e、 A依赖于B,B依赖于提供者,A中的某个方法f()调用B,B调用A中的某个方法,然后每次调用f()时都将创建A和B的新实例 将请求范围的对象注

根据,对于无状态对象,无范围绑定优于单例绑定

但我不同意这一说法,因为:

  • Singleton范围为开发人员提供了更多信息。开发人员可以假设单例对象是线程安全的,并且可以在大多数情况下在不使用提供程序的情况下注入它们
  • 由于与其他非作用域对象的依赖关系,创建非作用域对象的成本可能会很高
  • 非作用域对象的循环依赖只能通过提供程序来解决,这可能导致奇怪的行为。 e、 A依赖于B,B依赖于提供者,A中的某个方法f()调用B,B调用A中的某个方法,然后每次调用f()时都将创建A和B的新实例
  • 将请求范围的对象注入非范围对象时,很难判断是否需要提供程序,因为非范围对象的生命周期未知

  • 有人能解释为什么对于无状态对象,默认作用域优先于单例作用域吗?

    对于无作用域对象而不是单例对象,有一个重要的原因:单例对象永远不能被垃圾收集,它们所引用的对象的整个传递树也不能被垃圾收集。它们的构造需要同步(以防止创建过程中出现争用情况),然后它们在注入器的整个生命周期内都保留在内存中

    这是一个特别的问题,因为在生产环境中,无论它们是否绑定到AsagerSingleton。这意味着在生产环境中,单例树的内存承诺从创建注入器时开始,通常持续到应用程序关闭

    与明智地选择单例相比,将单例用于所有操作可能会导致启动速度减慢和内存需求增加

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


    作用域大致跟踪对象的生存期,目标是避免将范围较窄的对象注入范围较宽的对象(例如,保留未作用域的对象C,这可能与请求a相关,但与请求B无关)。这样做将是一种范围扩大的注入

    当您提到未限定范围的对象时,请将其视为短暂的或一次性的,并且具有尽可能狭窄的范围。这使得无状态对象不受范围限制变得特别容易,因为不管您拥有哪个实例

    这些未作用域的对象也可以在不使用提供程序的情况下自由地在图中注入任何对象,前提是与您选择的任何其他依赖项相比,未作用域的对象将始终具有更短的生存期。相比之下,单例必须为其所有非单例依赖项使用提供程序,因为它将绝对超过它所依赖的任何非单例

    正如您在上文第1和第4节中提到的,这应该清楚地表明您何时需要提供商



    总而言之,我只能告诉您:除非您有充分的理由(状态、昂贵的构造或资源管理),否则您可能应该让您的注入器不受影响。

    此外,wiki页面似乎非常清楚“如果对象是无状态且创建成本较低的,则无需进行范围界定”(强调)。这似乎使您的所有参数无效。Unscoped,或默认作用域,意味着绑定时没有作用域概念。Guice将在每次注入绑定时构造一个新的类实例。很抱歉输入错误:pA说,除非
    Y
    ,否则请使用
    x
    。B表示,使用
    y
    ,除非
    X
    :)谢谢你的详细解释,杰夫!不过,我觉得时间/内存消耗可能不是无范围对象的优势。设想一个具有高吞吐量的服务器应用程序,它可能需要构造许多无状态的非作用域对象,并且同一类的多个非作用域对象实例很可能在高峰时间一直留在内存中。对于单例,一旦服务器启动,就不会有构造和GC开销,并且内存中正好有一个实例。@user607722您刚才描述的正是您找不到“始终使用单例”或“从不使用单例”这样的规则的原因。每一个都会有自己的判断,这取决于dep的分量有多重以及持续需要的可能性有多大。希望我已经解释了为什么它们是首选的,并且您可以使用您的工程判断将优缺点应用到您的特定依赖项。
    injector ___________________TIME_________________________\
    creation                                                 /
    
    |---------------------SINGLETON-------------------------->
       |----------REQUEST A------------|   |---REQUEST B----->
          |-UNSCOPED C-| |-UNSCOPED D-|      |-UNSCOPED E-|