到底什么是现场注入以及如何避免它?

2024-02-23

我在一些关于 Spring MVC 和 Portlet 的文章中读到场注入不推荐。据我了解,场注入是当你注入一个 Bean 时@Autowired像这样:

@Component
public class MyComponent {
    @Autowired
    private Cart cart;
}

在我的研究过程中,我还读到构造函数注入:

@Component
public class MyComponent {
    private final Cart cart;

    @Autowired
    public MyComponent(Cart cart){
       this.cart = cart;
    }
}

这两种注射方式各有什么优点和缺点?


EDIT 1:由于这个问题被标记为重复这个问题 https://stackoverflow.com/questions/7779509/setter-di-vs-constructor-di-in-spring我查了一下。因为问题和答案中都没有任何代码示例,所以我不清楚我对我正在使用哪种注入类型的猜测是否正确。


注射类型

对于如何将依赖项注入到 bean 中,有以下三种选项:

  1. 通过构造函数
  2. 通过设置器或其他方法
  3. 通过反思,直接进入领域

您正在使用选项 3。这就是您使用时发生的情况@Autowired直接在您的领域。


注射指南

Edit: 这里提到的这 3 个链接适用于 Spring 4.2。有关 2023 年 (6.09) 的较新版本文档,请参阅下面的列表

一般准则,Spring推荐的 http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html(请参阅有关基于构造函数的 DI https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html#beans-constructor-injection or 基于 Setter 的 DI https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html#beans-setter-injection)如下:

  • 对于强制依赖项或以不变性为目标时,请使用构造函数注入
  • 对于可选或可更改的依赖项,请使用 setter 注入
  • 大多数情况下避免现场注入

现场注入的缺点

现场注入不受欢迎的原因如下:

  • 您无法像构造函数注入那样创建不可变对象
  • 您的类与 DI 容器紧密耦合,无法在其外部使用
  • 如果没有反射,您的类无法实例化(例如在单元测试中)。您需要 DI 容器来实例化它们,这使您的测试更像集成测试
  • 您真正的依赖项对外部隐藏,并且不会反映在您的接口(构造函数或方法)中
  • 拥有十个依赖项确实很容易。如果您使用构造函数注入,您将拥有一个带有十个参数的构造函数,这将表明某些内容存在可疑之处。但是您可以无限期地使用字段注入来添加注入字段。拥有太多依赖项是一个危险信号,表明该类通常会做不止一件事,并且可能违反单一职责原则。

结论

根据您的需要,您应该主要使用构造函数注入或构造函数和 setter 注入的某种组合。现场注入有许多缺点,应该避免。字段注入唯一的优点是编写起来比较方便,但这并不能抵消所有的缺点。


进一步阅读

我写了一篇关于为什么通常不推荐字段注入的博客文章:字段依赖注入被认为是有害的 http://vojtechruzicka.com/field-dependency-injection-considered-harmful/.


Spring文档

Spring 4.2(来自原始帖子)

  • 国际奥委会容器 https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/beans.html
  • 基于构造函数的依赖注入 https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/beans.html#beans-constructor-injection
  • 基于 Setter 的依赖注入 https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/beans.html#beans-setter-injection

Spring 6.0.9(2023 当前稳定版本)

  • 国际奥委会容器 https://docs.spring.io/spring-framework/reference/core/beans.html
  • 基于构造函数的依赖注入 https://docs.spring.io/spring-framework/reference/6.1-SNAPSHOT/core/beans/dependencies/factory-collaborators.html#beans-constructor-injection
  • 基于 Setter 的依赖注入 https://docs.spring.io/spring-framework/reference/6.1-SNAPSHOT/core/beans/dependencies/factory-collaborators.html#beans-setter-injection
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

到底什么是现场注入以及如何避免它? 的相关文章

  • Java - 从配置文件加密/解密用户名和密码

    我们正忙于为客户开发 Java Web 服务 有两种可能的选择 将加密的用户名 密码存储在Web服务客户端上 从配置中读取 文件在客户端 解密并发送 将加密的用户名 密码存储在 Web 服务器上 从配置中读取 Web 服务器上的文件 解密并
  • 如何降低圈复杂度?

    我正在开发一个将 RequestDTO 发送到 Web 服务的类 我需要在发送请求之前验证该请求 请求可以从 3 个不同的地方发送 并且每个 请求类型 有不同的验证规则 例如请求1必须有姓名和电话号码 请求2必须有地址等 我有一个 DTO
  • 在 Tomcat 上部署 Java Web 项目,无需 WAR 或 EAR

    我有一个 Java Web 项目 Struts Spring 在我的本地主机上完美运行 我必须将其部署在我的网站上 但虚拟主机提供的 Tomcat Manager 界面显示 由于安全原因 它无法上传 WAR 文件 当联系技术支持时 我被告知
  • 在哈希图中存储字符和二进制数

    我正在尝试存储字母到二进制数的映射 这是我的映射 h 001 i 010 k 011 l 100 r 101 s 110 t 111 为此 我创建了一个哈希映射并存储了键值对 我现在想显示给定句子的相应二进制值 这是我的代码 package
  • 使用 JAXB 编组 LocalDate

    我正在构建一系列链接类 我希望能够将其实例编组到 XML 以便我可以将它们保存到文件中并稍后再次读取它们 目前我使用以下代码作为测试用例 import javax xml bind annotation import javax xml b
  • 如果按下 Esc 则中断循环

    我用 JAVA 语言编写了一个程序 它使用 Scanner 类接受来自控制台的输入 现在我想将此功能添加到我的代码中 以便在用户按下 Esc 按钮时存在循环 while 到目前为止 我认为键盘类可以帮助我 但它就像扫描仪一样 我尝试使用事件
  • BigDecimal 的 JPA @Size 注释

    我该如何使用 SizeMySQL 的注释DECIMAL x y 列 我在用着BigDecimal 但是当我尝试包括 Size max它不起作用 这是我的代码 Size max 7 2 Column name weight private B
  • spring中如何进行单元测试验证注解

    我在类中有一些注释 例如 public class ProductModel Pattern regexp 1 1 9 0 9 message Quantity it should be number and greater than ze
  • 此版本不符合 Google Play 64 位要求,添加库后仍然出现错误

    我正在 Play 商店上传一个视频编辑器应用程序 其中包含带有一些本机代码的库 所以我通过将其添加到 gradle 来使其兼容 64 位 ndk abiFilters armeabi v7a arm64 v8a x86 x86 64 添加了
  • 如何在Gradle中支持多种语言(Java和Scala)的多个项目?

    我正在尝试将过时的 Ant 构建转换为 Gradle 该项目包含约50个Java子项目和10个Scala子项目 Java 项目仅包含 Java Scala 项目仅包含 Scala 每个项目都是由 Java 和 Scala 构建的 这大大减慢
  • 用于防止滥用的 Servlet 过滤器? (DoS、垃圾邮件等)

    我正在寻找一个 Servlet 过滤器库 它可以帮助我保护我们的 Web 服务免受未经授权的使用和 DDoS 攻击 我们的网络服务有 授权客户 因此理想情况下 过滤器将帮助检测未经授权或行为不当的客户 或检测使用同一帐户的多个人 此外 我们
  • JavaFx 中装饰且不可移动的舞台

    我想在 JavaFx 中创建一个装饰舞台 它也将不可移动 我正在从另一个控制器类创建这个阶段 我能够创造和展示舞台 但它是自由移动的 我怎样才能创建这个 非常感谢帮助和建议 我把打开新关卡的方法贴出来 private void addRec
  • Java 类:匿名类、嵌套类、私有类

    有人能解释一下Java中匿名类 嵌套类和私有类之间的区别吗 我想知道与每个相关的运行时成本以及每个编译器的方法 这样我就可以掌握哪个最适合用于例如性能 编译器优化的潜力 内存使用以及其他 Java 编码人员的普遍可接受性 我所说的匿名类是指
  • 删除 ArrayList 对象问题

    我在处理作业时遇到从 ArrayList 中删除对象的问题 如果我使用 正常 for 循环 它的工作原理如下 public void returnBook String isbn for int i 0 i lt booksBorrowed
  • 如何列出所有可用的 LookAndFeel 主题?

    如何列出所有可用的 LookAndFeel 主题 我想在 JComboBox 中显示以供用户选择 这真的很简单 public static UIManager LookAndFeelInfo getInstalledLookAndFeels
  • Hibernate @OneToMany 注释到底是如何工作的?

    我对 Hibernate 还很陌生 我正在通过教程学习它 我在理解到底如何一对多注释作品 所以我有这两个实体类 Student代表一个学生并且Guide代表指导学生的人 因此 每个学生都与一名向导相关联 但一名向导可以跟随多个学生 我想要一
  • C++ 中的 Java ArrayList [重复]

    这个问题在这里已经有答案了 在Java中我可以做 List
  • setKeyListener 将覆盖 setInputType 并更改键盘

    大家好 我在两个设备之间遇到问题 在实践中使用InputType和KeyListener我正在操纵一个EditText让它从数字键盘接收逗号和数字 有关更多背景信息 请检查我之前的question https stackoverflow c
  • java中wav文件转换为字节数组

    我的项目是 阿塞拜疆语音的语音识别 我必须编写一个程序来转换wav文件到字节数组 如何将音频文件转换为byte 基本上如第一个答案中的片段所描述 但不是BufferedInputStream use AudioSystem getAudio
  • 条件查询:按计数排序

    我正在尝试执行一个标准查询 该查询返回 stackoverflow 中回答最多的问题 例如常见问题解答 一个问题包含多个答案 我正在尝试使用标准查询返回按每个问题的答案数排序的回答最多的问题 任何人都知道我应该在 hibernate cri

随机推荐

  • NuGet 包管理器:“AutoMapper”已具有为“Microsoft.CSharp”定义的依赖项

    我尝试在 Visual Studio Premium 2012 上使用 NuGet 将 AutoMapper 添加为项目的依赖项 但失败 它说 手术失败 AutoMapper 已经定义了一个依赖项 微软 CSharp 我可以添加其他依赖项
  • Flutter 重定向到 initState 上的页面

    我有一个应用程序 您需要登录才能继续 例如使用 Google 我想在需要身份验证时重定向用户 但是当我运行Navigator of context pushNamed myroute 我收到以下错误 EXCEPTION CAUGHT BY
  • 如何从 firebase 中删除条目

    我正在探索 Firebase 的功能 我在如何使用 java 代码从 Firebase 中删除节点或条目时遇到了问题 我搜索了他们的API 网络版本确实提供了remove 函数 但java没有 有一个removeValue 方法上的Fire
  • FluentNHibernate Component.ColumnPrefix 未应用

    我最近升级了FluentNHibernate from v1 1 0 685 to v1 2 0 712 最新 对于NHibernate 2 1 我的问题似乎是使用的类Component ColumnPrefix 映射 例如 public
  • ret2libc 攻击不会生成 shell

    我执行了 ret2libc 一切正常 但 shell 没有生成 源代码是 include
  • JHipster 的正确 Eclipse 设置是什么?

    我在第一次尝试在 STS Eclipse 中编译 jhipster 项目时收到此错误 The type org springframework core NestedRuntimeException cannot be resolved I
  • 如何向 PyPi 分发类型提示?

    我致力于将 Python 3 5 类型提示添加到响应库中 但是当我测试进行分发时 sdist or bdist wheel 它没有安装我的 pyi文件 我可以看到它是发行版的一部分 但仅此而已 您可以在此处查看我在存储库中获得的内容 htt
  • 包含 jQuery $.post() 函数的函数的返回值

    我知道 AJAX 是异步的 等等 但我有以下代码 function doesUsernameExist element Check via AJAX POST if username already exists in the databa
  • 合并 2 个排序列表

    我被要求针对以下问题提出尽可能多的解决方案 编写一个函数 它接受两个数字列表 均假设为 按升序排列 并将它们合并到一个列表中 也在 升序 我的第一个解决方案是append list1 onto list2然后重新sort 然后我发现一个内置
  • Android Mono 中的自定义应用程序子类

    我试图创建一个 Android App Application 的子类来覆盖 OnCreate 但我无法让它工作 这是我的代码 namespace MonoAndroidAcra Application Debuggable true La
  • 如何访问 tcp 标头详细信息?

    就像我创建了套接字并将该套接字绑定到客户端一样 我能够连接两侧并能够发送任意数量的数据 它基本上是 TCP 套接字 我的问题是我想访问 TCP 标头详细信息以检查和设置某种操作的参数 但我无法做到这一点 我正在用户空间中工作 从套接字级别我
  • 如何使用 Mercurial“恢复”未更改的文件?

    我在我的计算机上安装了 Windows7 我必须更改所有权限 取得所有权 这显然 触及 了我的所有文件 现在所有内容似乎都被 修改 当我执行 hg status 时 但只有一些文件有实际更改 是否有一个命令我可以运行 以便我可以 提交 或
  • 如何在 wicket 1.5 中的页面加载时打开模式窗口

    我使用 wicket 1 4 x 一段时间 在这里找到的解决方案效果很好 如何在页面加载时打开模态对话框 https stackoverflow com questions 4765790 how to open modaldialog o
  • 如何在 VBA 中替换范围/选择范围内的 Microsoft Word 字符样式?

    我正在开发一个带有宏的 Word 2007 模板 该宏会将字符样式应用于所选文本 查找 替换功能似乎是一个很好的起点 但我认为我发现了一个错误 限制 导致宏无法按预期工作 这是我的 vba 代码 Sub restyleSelection D
  • 如何检查按钮形状是否启用? [复制]

    这个问题在这里已经有答案了 如何使用 UIAccessibility 检查 iOS 设备辅助功能设置中的 按钮形状 选项是否已启用 我想在定制按钮上支持 按钮样式 我将代码转换为this https stackoverflow com a
  • 我如何使用 Node.js 和 Mongoose 计算总正价、总负价和总和

    我已经编写了获取所有用户记录的查询 exports index function req res Userdata find function err userdatas if err return handleError res err
  • 如何在React Native中使用全局变量?

    在 React Native 中 当我在不同屏幕之间移动时 我想使用全局变量 谁能帮助我如何实现它 React Native 中的全局范围是全局变量 例如global foo foo 那么你可以在任何地方使用 global foo 但不要滥
  • Spring 批处理:在 CompositeItemWriter 中使用 before-step 和 after-step 方法

    我需要从数据库读取数据 然后生成 XLSX 文件并更新数据库中的数据 对于读者部分来说没有问题 对于作家部分 我最终创建了一个CompositeItemWriter 由第一个组成Writer生成 XLSX 文件和更新数据库中数据的第二个文件
  • 我们应该使用 OpenGL 来处理 2D 图形吗?

    如果我们想做一个像MS Paint这样的应用程序 我们应该使用OpenGL来渲染图形吗 我想谈谈使用传统 GDI 与 OpenGL 时的性能 如果有一些更好的库用于此目的 请看我的一个 GDI X11 OpenGL 都是渲染 API 即您通
  • 到底什么是现场注入以及如何避免它?

    我在一些关于 Spring MVC 和 Portlet 的文章中读到场注入不推荐 据我了解 场注入是当你注入一个 Bean 时 Autowired像这样 Component public class MyComponent Autowire