@Autowired 注解为什么不建议开发者在 Spring 中使用?

huangapple go评论108阅读模式
英文:

Which an annotation @Autowired is not recommended for use by developers Spring and why?

问题

哪种来自 Autowiring for beans 的方式不建议 开发者Spring 中使用?为什么?

(我的意思是为什么他们不推荐使用 @Autowired)

当我们在 Spring 中指定哪些 beans 应该嵌入到其他类中时,我们例如会使用 @Autowired

但是不推荐使用这个注解,而推荐使用 数据绑定(Data Binding),为什么?

以下是作为附加回答的内容(可能与主要问题间接相关)...

谁能解释一下这个问题中的一些陷阱,以及在构造函数或设置器上设置 @Autowired 注解与之不同,在哪些情况下什么是更可取的?

英文:

Which from ways Autowiring for beans is not recommended for use by developers Spring and why ?

(I mean why they don't recommend to use @Autowired)

When we specify for Spring which beans it should embed in other classes, then we for example, use @Autowired.

But this annotation is not recommended for use, but Data Binding is recommended why ?.

This is the following answer as an additional one(may be related indirectly to the main question)...

Who can explain the pitfalls in this issue and how is different to set the annotation @Autowired over the constructor or setter, in which cases what is preferable ?

答案1

得分: 2

在他们的文档中,Spring团队写了一个相当好的解释,其中提到:

基于构造函数还是基于Setter的依赖注入(DI)?

由于可以混合使用基于构造函数和基于Setter的DI,一个经验法则是使用构造函数来注入必需的依赖项,而使用Setter方法或配置方法来注入可选的依赖项。
注意,在Setter方法上使用@Required注解可以将属性设置为必需依赖项;然而,通过编程验证参数的构造函数注入更可取。

Spring团队通常倡导使用构造函数注入,因为它允许您将应用程序组件实现为不可变对象,并确保必需的依赖项不为null。此外,通过构造函数注入的组件始终以完全初始化的状态返回给客户端(调用)代码。另一方面,大量的构造函数参数是糟糕的代码味道,暗示该类可能具有过多的职责,应进行重构以更好地处理关注点的适当分离。

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

使用最适合特定类的DI风格。有时,在处理源代码不可用的第三方类时,选择已经为您做出。例如,如果第三方类没有公开任何Setter方法,则构造函数注入可能是唯一可用的DI形式。

因此,一般建议对必需字段使用构造函数注入,对可选字段使用Setter注入,但需要注意的是,如果使用Setter注入,您将放弃不可变性的好处。被不鼓励的是字段注入,因为它需要使用Java反射机制来填充字段,这会导致您的代码与Spring的机制紧密耦合,并且还会使得单元测试变得更加困难,因为您不能轻松地通过构造函数或Setter传递模拟对象。

英文:

There is a quite good explanation written by the Spring team in their documentation, where it says:

> Constructor-based or setter-based DI?
>
> Since you can mix constructor-based and setter-based DI, it is a good
> rule of thumb to use constructors for mandatory dependencies and
> setter methods or configuration methods for optional dependencies.
> Note that use of the @Required annotation on a setter method can be
> used to make the property be a required dependency; however,
> constructor injection with programmatic validation of arguments is
> preferable.
>
> The Spring team generally advocates constructor injection, as it lets
> you implement application components as immutable objects and ensures
> that required dependencies are not null. Furthermore,
> constructor-injected components are always returned to the client
> (calling) code in a fully initialized state. As a side note, a large
> number of constructor arguments is a bad code smell, implying that the
> class likely has too many responsibilities and should be refactored to
> better address proper separation of concerns.
>
> Setter injection should primarily only be used for optional
> dependencies that can be assigned reasonable default values within the
> class. Otherwise, not-null checks must be performed everywhere the
> code uses the dependency. One benefit of setter injection is that
> setter methods make objects of that class amenable to reconfiguration
> or re-injection later. Management through JMX MBeans is therefore a
> compelling use case for setter injection.
>
> Use the DI style that makes the most sense for a particular class.
> Sometimes, when dealing with third-party classes for which you do not
> have the source, the choice is made for you. For example, if a
> third-party class does not expose any setter methods, then constructor
> injection may be the only available form of DI.

So in general it is recommended to use constructor injection for mandatory fields and setter injection for optional fields, but be careful, because if you are using setter injection, you renounce the goodness of immutables. What is discouraged is definetely field injection, as it needs to use java reflection mechanism to populate your fields, which has this consequence that you couple your code very tightly with spring's mechanisms and also it makes your unit tests much harder, as you cannot so easilly pass a mock object via a constructor or setter.

huangapple
  • 本文由 发表于 2020年9月26日 16:22:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/64075468.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定