Dagger 2:何时使用构造函数注入,何时使用字段注入?

2024-04-25

我有点懒,过去几乎完全使用现场注入。我只是提供空的构造函数,放入我的 @Inject 字段,我的一切看起来都很好很简单。然而,字段注入有其权衡,因此我设计了一些简单的规则来帮助我决定何时使用字段以及何时使用构造函数注入。如果我的逻辑有错误或者您有其他注意事项需要添加,我将不胜感激。

首先进行一些澄清,以便在同一页面上:

构造函数注入:

@Inject
public SomeClass(@Named("app version") String appVersion,
                    AppPrefs appPrefs) {...

与现场注入相同:

public class SomeClass {
    @Inject
    @Named("app version") String mAppVersion;

    @Inject
    AppPrefs appPrefs;

规则 1:如果我不控制对象的创建,则必须使用字段注入(想想 Android 中的 Activity 或 Fragment)。如果某些(非匕首感知)框架正在创建我的对象并为我处理它,我别无选择,只能在收到实例后手动注入它。

规则 2:如果该类在/可能在另一个不使用 Dagger 2 的项目中使用,则必须使用构造函数注入。如果其他项目不使用 Dagger,它们就无法使用 DI,因此用户必须使用“旧”方式创建对象new.

规则 3:在使用类层次结构时首选构造函数注入,因为创建单元测试更容易。

澄清:

考虑以下使用字段注入的结构:

package superclass;

public class SuperClass {
    @Inject
    HttpClient mHttpClient;
    ...
}

.

package differentpackage;

public class SubClass extends SuperClass {
    public SubClass() {
    }
}

当我为以下内容创建单元测试时SubClass在目录中test/java/differentpackage我别无选择,只能启动整个 DI 基础设施,以便能够注入HttpClient。相反,如果我使用这样的构造函数注入:

public class SuperClass {
    private final HttpClient mHttpClient;

    @Inject
    public SuperClass(HttpClient httpClient) {
        mHttpClient = httpClient;
    }
}

在我的单元测试中我可以简单地:

HttpClient mockHttp = mock(HttpClient.class);

Subclass tested = new Subclass(mockHttp);

// tests 

所以基本上现在我处于另一个极端:我倾向于主要依赖构造函数注入,并且仅在“规则 1”适用时才使用字段注入。 我在构造函数注入方面遇到的唯一“问题”是,对于“最终”类,构造函数有时会变得参数超载,并且它们看起来冗长且丑陋,如下所示:

@Inject
public ModelMainImpl(@Named("app version") String appVersion,
                    AppPrefs appPrefs,
                    LoginPrefs loginPrefs,
                    @ForApplication Context appContext,
                    NetworkInfoProvider networkInfoProvider,
                    AndroidEventPoster androidEventPoster,
                    Session session,
                    ForgeExchangeManager exchangeManager,
                    HttpFunctionality httpFunctionality,
                    @Named("base url") String baseUrl,
                    @Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer
                    ) {

伙计们,在构造函数注入和字段注入之间选择的规则是什么?我遗漏了一些东西,我的逻辑有问题吗?


使用构造函数注入。如果不能,请使用属性注入。

规则 1 似乎没问题,就像装饰或属性一样,您可以使用 Property(field) 注入。

规则 2 似乎没问题,因为谁使用你的类,他们就必须遵循你的构造函数。他们可能不知道他们也必须侵犯您的财产。

规则 3 它不仅仅有利于单元测试。这对于应用单一职责很有好处。更容易看到你的对象图。否则你会用属性隐藏它。

如果我们提出您的问题,是的,您的构造函数中有很多参数。但是解决方案不是属性注入。您可以重构您的代码并使用聚合服务 http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dagger 2:何时使用构造函数注入,何时使用字段注入? 的相关文章

  • 在Maven中生成Version.java文件

    我有一个使用 Ant 脚本构建的 Java 项目 我正在尝试将项目转换为 Maven 其中一项任务生成一个名为 Version java 的 Java 源文件 其中包含编译时间戳的静态字符串表示形式 如下所示 package com foo
  • “源兼容性”和“目标兼容性”有什么区别?

    之间有什么关系 区别sourceCompatibility and targetCompatibility 当它们设置为不同的值时会发生什么 根据工具链和兼容性 https docs gradle org current userguide
  • Kafka - 如何同时使用过滤器和过滤器?

    我有一个 Kafka 流 它从一个主题获取数据 并且需要将该信息过滤到两个不同的主题 KStream
  • 如何在 Android 应用程序中隐藏 Flutterwave API 密钥

    我正在构建一个 Android 应用程序 目前正在将 Flutterwave 集成到我的应用程序中以进行支付 建议我永远不要将 Flutterwave API 密钥放在我的应用程序上 那么我该如何隐藏这些键呢 我正在使用 Retrofit
  • Java 中的 <-- 是什么? [复制]

    这个问题在这里已经有答案了 我遇到了下面的片段 它输出到4 3 2 1 我从来没有遇到过 lt 在爪哇 Is lt 使 var1 的值变为 var2 的运算符 public class Test public static void mai
  • 使用 Exec Maven 插件分叉 Java,而不使用“exec”目标

    来自文档 https www mojohaus org exec maven plugin exec exec在单独的进程中执行程序和Java程序 exec java在同一虚拟机中执行 Java 程序 我想 fork 一个 java 程序
  • 我们可以有条件地声明 spring bean 吗?

    有没有一种方法可以有条件地声明 Spring bean 例如
  • 什么是内部类的合成反向引用

    我正在寻找应用程序中的内存泄漏 我正在使用的探查器告诉我寻找这些类型的引用 但我不知道我在寻找什么 有人可以解释一下吗 Thanks Elliott 您可以对 OUTER 类进行合成反向引用 但不能对内部类实例进行合成 e g class
  • 为什么用scala写的代码比用java写的慢6倍?

    我不确定我在编写 scala 代码时是否犯了一些错误 问题是 The four adjacent digits in the 1000 digit number that have the greatest product are 9 9
  • 未装饰窗户的 Windows Snap 功能?

    有谁知道如何允许未装饰的窗户使用此功能 唯一的选择就是重新实施它 有任何想法吗 谢谢 可停靠可能是唯一的JToolBar http docs oracle com javase tutorial uiswing components too
  • ThreeTen 向后移植与 JSR-310 的比较

    由于某些原因 我们现在无法使用 java 8 我们仍然停留在 java 7 上 不过 我想使用新的JSR 310 date time APIs现在 使用官方向后移植 ThreeTen http www threeten org threet
  • Mockito 和 Hamcrest:如何验证 Collection 参数的调用?

    我遇到了 Mockito 和 Hamcrest 的泛型问题 请假设以下界面 public interface Service void perform Collection
  • 如何更改 Swagger-ui URL 前缀?

    我正在使用 Springfox Swagger2 和 Spring boot 1 5 9 我可以通过此链接访问 swagger UI http localhost 8090 swagger ui html http localhost 80
  • 为什么解析这个 JSON 会抛出错误?

    我正在尝试解析这个 JSONObject query yahoo count 1 results rate Name USD INR id USDINR Time 12 19pm Date 10 31 2015 Bid 65 405 Ask
  • 如何在 IntelliJ IDEA 中运行 akka actor

    来自 Akka 网站文档 然后 这个主要方法将创建所需的基础设施 运行演员 启动给定的主要演员并安排 一旦主要参与者终止 整个应用程序就会关闭 因此 您将能够使用类似于以下的命令运行上面的代码 下列的 java classpath akka
  • Tomcat 6 未从 WEB-INF/lib 加载 jar

    我正在尝试找出我的 tomcat 环境中的配置问题 我们的生产服务器正在运行 tomcat 安装并从共享 NFS 挂载读取战争 然而 当我尝试使用独立的盒子 及其配置 进行同样的战争时 我收到下面发布的错误 有趣的是 如果我将 WEB IN
  • Spring Data Rest 多对多 POST

    首先 让我解释一下我的用例 这非常简单 有一个用户实体和一个服务实体 我使用 UserService 作为连接实体 连接表 在用户和服务之间建立多对多关联最初 会有一些用户集和一些服务集 用户可以在任何时间点订阅任何服务 在这种情况下 将向
  • 确定 JavaFX 中是否消耗了事件

    我正在尝试使用 JavaFX 中的事件处理来做一些非滑雪道的事情 我需要能够确定手动触发事件后是否已消耗该事件 在以下示例中 正确接收了合成鼠标事件 但调用 Consumer 不会更新该事件 我对此进行了调试 发现 JavaFX 实际上创建
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据
  • 使用 DBCP 配置 Tomcat

    在闲置一段时间 几个小时 后 我们收到了 CommunicationsException 来自 DBCP 错误消息 在异常中 位于这个问题的末尾 但我没有看到任何配置文件中定义的 wait timeout 我们应该看哪里 在 tomcat

随机推荐

  • 安装期间初始化 user.config 或 app.exe.config

    我正在开发一个 NET WinForms 应用程序 它依赖于 user config 来存储各种有用的设置 例如 Intranet Web 服务 URL 我们希望能够在安装过程中导入自定义初始设置 其用例是 如果一家公司想要在 100 台计
  • Spring Boot - 微服务之间如何通信?

    我目前正在开发一个 Spring Boot 微服务项目 我创建了服务 每个服务都单独运行 这样 我需要一些服务来与其他服务进行通信 我怎样才能做到这一点 我看到一些关于此的博客使用 Netflix Eureka 云服务器来实现这一点 有什么
  • mysql中auto_increment(整数)的限制是多少

    我有一个mysql数据库 我在其中使用auto increment integer 你能告诉我它可以增加多少整数吗 我们如何提高auto increment的限制 的极限auto increment column 是列的大小 https d
  • PHP / OpenCart 2.2.0 - 创建自定义主题

    我今天开始在 OpenCart 2 2 中进行主题开发 我正在关注这篇文章 http code tutsplus com tutorials create a custom theme with opencart introduction
  • 类型错误:“itertools.combinations”对象不可下标

    当我尝试运行时 temp twoset2 x i 0 twoset x i 1 I get 类型错误 itertools combinations 对象不可下标 My code for x in range 0 64 for i in ra
  • 如何在动态更新时检测输入的值变化(Angular 6)

    我正在使用自定义指令和自定义管道对文本输入进行货币格式化 它适用于任何类型的直接用户输入 焦点 模糊 按键 但是 当值动态更改时 我似乎无法捕获更改事件 我也找不到可靠的主机侦听器事件列表 并且不知道如何捕获进入输入的任何事件 因此无法看到
  • 如何在 API 模式下使用 Doorkeeper 处理 OAuth 流程?

    场景很简单 A 仅限 Rails API带有 Doorkeeper 提供商的服务器 A 移动应用 and a SPA 假设是 React 想要使用电子邮件和密码注册和登录的用户 当你有一个正常的Rails 堆栈 你需要定义一个authori
  • RecyclerView 和 Picasso 图像滚动后消失

    我没有找到答案here https stackoverflow com questions 29564824 recyclerview disappearing images here https stackoverflow com que
  • GWT 和 Google 文档 API

    我正在使用 GWT 创建一个简单的应用程序 让教师可以轻松创建自己的课程 该应用程序将位于 Google App Engine 上 但我想将课程存储在用户的 Google 文档空间中 是否可以 据我所知 gwt 将 java 转换为 jav
  • 未捕获的错误:期望增强器是一个函数

    我试图从组件调用减速器并希望在组件中渲染它 但是当我尝试将减速器存储在 redux 的 createStore 方法中时 出现了上述错误 我的代码是这样的 import applyMiddleware compose createStore
  • Powershell Invoke-RestMethod 授权标头

    当调用一个Invoke RestMethod使用 Powershell 例如 Invoke RestMethod Method Get Uri https google com api GetData Headers headers and
  • Pandas 读取缺少一个标头的 csv

    我正在尝试使用 Pandas 读取 csv 文件 但第一列包含用逗号分隔的名字和姓氏 这会导致 Pandas 认为有 5 列而不是 4 列 因此最后一列现在没有标题 因此无法选择它 该文件如下所示 CustomerName ClientID
  • 在 SQL 中将字符串拆分为多行

    我继承了一个数据库 在努力使其更干净 更有用的过程中 我遇到了以下问题 将文件列移动到单独的表后 我现在的任务是将这些文件分成不同的行 请看我下面的例子 key jobid files 1 30012 file1 pdf file2 pdf
  • SSRS 聚合聚合

    这两天我都在用头撞墙 我的场景是这样的 我有一个记录集 在 SSRS 表中分为 4 组 他们是 StartPeriod gt Area gt Job gt Details 相关列包含两个不同的记录计数 一个是有错误的记录数 另一个是该组的记
  • SWI-Prolog 中的约束编程

    我想要一个包含三个元素 A B 和 C 的列表 L 并具有以下约束 use module library clpfd L A B C L ins 1 3 A B C 但是 它给出了一个错误 Syntax error Operator exp
  • UIViewController 弹出时未释放

    我有一个表视图 当选择一个单元格时 它将视图控制器推送到导航堆栈上 SAPostTableViewController postViewController SAPostTableViewController alloc initWithN
  • android kotlin java.io.FileNotFoundException:/storage/emulated/0/number.txt:打开失败:EACCES(权限被拒绝)

    我正在使用 kotlin 为 Android 10 编写一个应用程序 该应用程序必须读取名为number txt来自内部存储 但它总是失败 java io FileNotFoundException storage emulated 0 n
  • 在 Java 8 中使用 Java 7 比较器

    情况 我有一个 OSGi 项目 我正在尝试迁移到 Java 8 在我的项目中 我依赖于我 OSGi fied 的第三方库 只需添加MANIFEST MF文件并将元数据放入其中 这些库是从只读 SVN 存储库中签出的 因此我可以在需要时签出更
  • 在 iframe 中显示缩略图

    我在这方面还很陌生 我有以下内容iframe 我想做的就是让它发挥作用video1 1 但显示其中的图像video1 2 我尝试做的是 但这行不通 有简单的方法吗 iFrame 标记中没有 href 属性 看 http www w3scho
  • Dagger 2:何时使用构造函数注入,何时使用字段注入?

    我有点懒 过去几乎完全使用现场注入 我只是提供空的构造函数 放入我的 Inject 字段 我的一切看起来都很好很简单 然而 字段注入有其权衡 因此我设计了一些简单的规则来帮助我决定何时使用字段以及何时使用构造函数注入 如果我的逻辑有错误或者