Spring有两种类型的DI:setter DI和构造DI。
基于构造函数的DI修复了需要注入依赖项的顺序。基于Setter的DI不提供此功能。
基于Setter的DI帮助我们仅在需要时注入依赖关系,而不是在构造时需要它。
我没有看到任何其他显着差异,因为两种类型的Spring DI都提供相同的功能 - setter和构造函数DI在代码启动时注入依赖关系。当然,构造函数DI将通过构造函数执行,而setter DI将在构造对象后立即通过setter执行它,但它在性能等方面对开发人员没有任何影响。两者都提供了指定顺序的方法依赖注入也是如此。
我正在寻找一个场景,其中一个提供明显的优势,或者一个类型完全无法使用。
答案 0 :(得分:24)
说到Spring特定的利弊:
构造函数注入(来自定义)不允许您在bean之间创建循环依赖关系。这个限制实际上是构造函数注入的一个优点 - 当使用setter注入时,Spring可以解决循环依赖关系而你甚至没有注意到。
另一方面,如果使用构造函数注入CGLIB无法创建代理,则强制您使用基于接口的代理或虚拟无参数构造函数。请参阅:SPR-3150
答案 1 :(得分:16)
您应该根据设计考虑而不是工具(Spring)考虑做出决定。不幸的是,Spring已经训练我们使用setter注入,因为当它最初构思时,Java中没有“注释”这样的东西,而在XML中,setter注入工作并且看起来更好。今天,我们摆脱了这些限制,从而使它再次成为一个设计决策。你的bean应该对bean和setter注入所需的任何依赖项使用构造函数注入,这些依赖项是可选的,并且具有合理的默认值,或多或少,正如OOD从一开始就告诉我们的那样。
答案 2 :(得分:9)
构造函数注入:我们通过Constructor注入依赖项。
通常我们可以使用 强制依赖。
如果使用构造函数注入,则存在一个称为“循环依赖”的缺点。
循环依赖:假设A和B. A依赖于B. B依赖于A.在此构造函数中,注入将失败。那时,Setter注射很有用。
如果对象状态不一致,则不会创建对象。
Setter Injection:我们通过Setter方法注入依赖项。
这对非强制性依赖项非常有用。
使用 Setter Injection可以重新注入依赖关系。 构造函数注入 。
答案 3 :(得分:2)
根据Spring 5以后的spring.io中的内容
由于您可以混合使用基于构造函数的DI和基于setter的DI,因此,将构造函数用于强制性依赖项,将setter方法或配置方法用于可选性依赖项是一个很好的经验法则。请注意,可以在setter方法上使用@Required批注,以使该属性成为必需的依赖项。
Spring团队通常提倡构造函数注入,因为它使人们能够将应用程序组件实现为不可变对象,并确保所需的依赖项不为null。此外,注入构造函数的组件总是以完全初始化的状态返回到客户端(调用)代码。附带说明一下,大量的构造函数参数是一种不好的代码味道,这表明该类可能承担了太多的责任,应该对其进行重构以更好地解决关注点分离问题。
Setter注入主要应仅用于可在类中分配合理的默认值的可选依赖项。否则,必须在代码使用依赖项的任何地方执行非空检查。 setter注入的一个好处是,setter方法使该类的对象在以后可以重新配置或重新注入。因此,通过JMX MBean进行管理是塞特注入的引人注目的用例。
这是上面引用的link
但是,所有注入类型均可用,并且都不弃用。从总体上讲,您可以在所有注射类型上获得相同的功能。
简而言之,选择最适合您的团队和项目的注入类型。
Spring团队的建议和独立博客文章会随时间而变化。没有硬性规定。
如果Spring团队不建议使用特定的注入方式,则他们会将其标记为已弃用或过时。任何一种注入样式都不是这种情况。
答案 4 :(得分:1)
喜欢二传手注射。
想想没有春天会是什么(正如Ryan所说)。你会在构造函数中传递依赖项吗?如果有太多依赖项,这似乎是错误的。另一方面,构造函数可用于强制执行对象的有效状态 - 需要所有依赖项并验证它们是否为非null。
代理是另一回事(正如Tomasz所说) - 你需要一个虚拟构造函数来击败整个想法。
第三种选择btw - 现场注射。我倾向于使用它,虽然它不是一个好的设计决定,因为它节省了额外的设置器,但如果在春天之外使用它我将不得不添加设置器。
答案 5 :(得分:0)
既然你可以混合两种,构造函数DI - 和基于Setter的DI ,那么 使用构造函数参数作为可选依赖项的强制依赖项和setter 。
注意在setter上使用@Required注释可用于使setter成为必需的依赖项。
答案 6 :(得分:0)
我的2美分。 假设有10个字段的classA,其中注入的依赖项很少。 现在,如果您需要包含所有字段的整个classA,则可以进行构造函数注入。 但是,如果您只需要一个注入字段在该课程中使用,则可以使用设置注入。
这样,
答案 7 :(得分:0)
这可能不是主要优势。但是让我解释一下Spring中的注入机制。
这两种方法的区别在于,使用@ Inject,@ Autowire等进行注入的方式,Spring将使用反射将一个bean注入另一个bean,并且通过构造函数的方式,我们自己按顺序使用构造函数在不使用反射的情况下由另一个bean初始化一个bean。因此,使用构造函数的方式会提供更好的其他选择,至少我们不使用反射机制,因为从机器方面来说,反射是一项昂贵的操作。
附言请考虑,构造DI的正确用法是当您使用带参数的构造函数手动创建bean时,即使您可以在没有任何构造函数的情况下使用构造函数进行创建。
答案 8 :(得分:-1)
不,甚至构造函数注入发生,注入仍在工作,但只是初始化有限,setter注入是可选的和灵活的。但它通常可以用于参数类,一个带有其他spring bean的spring bean