Setter DI与Spring中的Constructor DI?

M S*_*ach 25 spring dependency-injection

弹簧有两种类型的DI:定位器DI和结构DI.

基于构造函数的DI修复了需要注入依赖项的顺序.基于Setter的DI不提供此功能.

基于Setter的DI帮助我们仅在需要时注入依赖项,而不是在构造时需要它.

我没有看到任何其他显着差异,因为两种类型的Spring DI都提供相同的功能 - 设置器和构造函数DI在代码启动时注入依赖关系.当然,构造函数DI将通过构造函数执行,而setter DI将在构造对象后立即通过setter执行它,但它在性能等方面对开发人员没有任何影响.两者都提供了指定顺序的方法依赖注入也是如此.

我正在寻找一个场景,其中一个提供明显优势,或一个类型完全无法使用.

Tom*_*icz 26

说到Spring的具体优缺点:

  • 构造函数注入(来自定义)不允许您在bean之间创建循环依赖关系.这个限制实际上是构造函数注入的一个优点 - 当使用setter注入时,Spring可以解决循环依赖关系而你甚至没有注意到.

  • 另一方面,如果使用构造函数注入CGLIB无法创建代理,则强制您使用基于接口的代理或虚拟无参数构造函数.见:SPR-3150

  • 想一想:如果bean A在启动时需要bean B的实例而bean B需要bean A的实例,则无法实例化它们.当Spring检测到这种情况时,它会在启动时抛出异常.但是使用setter/field注入Spring可以创建实例然后注入它们,在这种情况下没问题. (4认同)
  • 但是,如果这是您项目中的常见问题,那么除了 DI 样式之外,您可能还有其他事情需要担心。 (2认同)

Rya*_*art 17

您应该根据设计考虑而不是工具(Spring)考虑做出决定.不幸的是,Spring已经训练我们使用setter注入,因为当它最初构思时,Java中没有"注释"这样的东西,而在XML中,setter注入工作并且看起来更好.今天,我们摆脱了这些限制,从而使它再次成为一个设计决策.你的bean应该使用构造函数注入来为bean和setter注入所需的任何依赖项,这些依赖项是可选的,并且具有合理的默认值,或多或少,正如OOD从一开始就告诉我们的那样.


Ran*_*ddy 10

构造函数注入:我们通过Constructor注入依赖项.

通常我们可以使用强制依赖.

如果使用构造函数注入,则存在一个称为"循环依赖"的缺点.

循环依赖:假设A和B.A依赖于B.B依赖于A.在此构造函数中,注入将失败.那时Setter注射很有用.

如果Object状态不一致,则不会创建Object.

Setter Injection:我们通过Setter方法注入依赖项.

这对非强制性依赖项很有用.

可以使用Setter Injection 重新注入依赖项.构造函数注入中不可能的.

  • 为什么您将防止循环依赖称为劣势?我认为这是一种优势,因为它可以防止程序员紧密耦合。 (2认同)

dam*_*mon 6

根据 spring.io 从 Spring 5 开始的内容

由于您可以混合使用基于构造函数和基于 setter 的 DI,因此根据经验,对强制依赖项使用构造函数,对可选依赖项使用 setter 方法或配置方法是一个很好的经验法则。请注意,在 setter 方法上使用 @Required 注释可用于使属性成为必需的依赖项。

Spring 团队通常提倡构造函数注入,因为它使人们能够将应用程序组件实现为不可变对象,并确保所需的依赖项不为空。此外,构造函数注入的组件总是以完全初始化的状态返回给客户端(调用)代码。作为旁注,大量的构造函数参数是一种糟糕的代码味道,这意味着该类可能有太多的责任,应该重构以更好地解决适当的关注点分离问题。

Setter 注入应该主要仅用于可以在类中分配合理默认值的可选依赖项。否则,必须在代码使用依赖项的任何地方执行非空检查。setter 注入的一个好处是 setter 方法使该类的对象可以在以后重新配置或重新注入。因此,通过 JMX MBean 进行管理是 setter 注入的一个引人注目的用例。

这是上面报价的链接

但是,所有的注入类型都可用,并且没有一个被弃用。在高层次上,您可以在所有注入类型中获得相同的功能。

简而言之,选择最适合您的团队和项目的注入类型。

Spring 团队和独立博客文章的建议会随着时间的推移而变化。没有硬性规定。

如果 Spring 团队不推荐特定的注入风格,那么他们会将其标记为已弃用或过时。任何注入方式都不是这种情况。