寻找 Dagger 辅助注射的示例

2024-05-07

From 匕首讨论@ https://groups.google.com/forum/#!topic/dagger-discuss/QgnvmZ-dH9c:

我有一个类,它从对象图中获取一些依赖项,并在运行时从调用者获取其他依赖项。

public class ImageDownloader {
  // Get these dependencies from the injector.
  private final HttpClient httpClient;
  private final ExecutorService executorService;

  // Get these from the caller.
  private final URL imageUrl;
  private final ImageCallback callback;

  ...
}

我想出了一个解决方案,我定义了一个工厂,

public class ImageDownloader {
  ...
  public static class Factory {
    private final HttpClient httpClient;
    private final ExecutorService executorService;

    @Inject
    public Factory(HttpClient httpClient, ExecutorService executorService) {
      this.httpclient = httpClient;
      this.executorService = executorService;
    }

    public ImageDownloader create(URL imageUrl, ImageCallback callback) {
      return new ImageDownloader(httpClient, executorService, iamgeUrl, callback);
    }
  }
  ...
}

现在,而不是注射ImageDownloader在客户端的构造函数中,我只需注入ImageDownloader.Factory并称其为create() method.

正如您所看到的,这非常冗长。它还包含大量重复内容和样板文件。对字段本身进行注释存在一些障碍@Inject,所以我们暂时忽略这种可能性。

Square 人员使用提供商提出了一个有趣的解决方案。定义一个Factory界面,

public class ImageDownloader {
  ...
  public interface Factory {
    ImageDownloader create(URL imageUrl, ImageCallback callback);
  }
}

然后在模块中提供它,

public class ImageModule {
  ...
  @Provides 
  public ImageModule.Factory provideImageModuleFactory(
      final Provider<HttpClient> httpClientProvider, 
      final Provider<ExecutorService> executorServiceProvider) {
    return new ImageDownloader.Factory() {
      public ImageDownloader create(URL imageUrl, ImageCallback callback) {
        return new ImageDownloader(httpClientProvider.get(), executorServiceProvider.get(),
            imageUrl, callback);
      }
  }
  ...
}

(再次来自 dagger-discuss@)。

My ImageDownloader是一个由一个类注入的类,该类由另一个类注入,而另一个类又由另一个类注入,...,它在@Module。这一切都以某种方式*起作用,并且所有类都在构建时找到。现在,要添加模块,我必须显式地让对象图知道它。

我一定错过了一些东西——注入一个新类很容易,但添加一个新模块却很乏味。

我的问题是:辅助注射在实践中是如何进行的?有人有例子吗?我应该如何使用ImageModule,如果有的话?

* - “不知怎的”确实意味着它对我来说有一定的魔力。


因此,Google 的一些 Dagger/Guice 人员创建了一个名为 AutoFactory 的东西(http://github.com/google/auto http://github.com/google/auto)在一个项目中,该项目包括 AutoFactory(代码生成的辅助注入)、AutoValue(代码生成的自定义值类型)和 AutoService(自动生成 java 服务元数据文件)。

AutoFactory 的运行方式几乎与您所期望的一样 - 它生成您原本需要手动创建的工厂。这是一个非常早期的版本,我们计划了更多的灵活性,但它将生成一个工厂类,该类将采用包含一些 JSR-330 可注入依赖项和一些调用堆栈参数的类型,并将它们合并在一起以创建带注释的类型。

本质上,如果您正确注释工厂创建的类型,它将自动生成您编写的工厂。

例如,如果您创建类:

@AutoFactory
public class ImageDownloader {
  // Get these dependencies from the injector.
  private final HttpClient httpClient;
  private final ExecutorService executorService;

  // Get these from the caller.
  private final URL imageUrl;
  private final ImageCallback callback;

  ImageDownloader(
      @Provided HttpClient httpClient,
      @Provided ExecutorService executorService,
      ImageCallback callback,
      URL imageUrl) {
    // assignments
  }
}

AutoFactory 将生成:

@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class ImageDownloaderFactory {
  private final Provider<ExampleClasses.HttpClient> httpClientProvider;
  private final Provider<java.util.concurrent.ExecutorService> executorServiceProvider;

  @Inject
  public ImageDownloaderFactory(
      Provider<ExampleClasses.HttpClient> httpClientProvider,
      Provider<java.util.concurrent.ExecutorService> executorServiceProvider) {
    this.httpClientProvider = httpClientProvider;
    this.executorServiceProvider = executorServiceProvider;
  }

  public ImageDownloader create(ImageCallback callback, URL imageUrl) {
    return new ImageDownloader(
        httpClientProvider.get(), 
        executorServiceProvider.get(), 
        callback, 
        imageUrl);
  }
}

(请注意,我们需要对输出源进行大量清理,但上面基本上是生成的内容,尽管格式不那么好。)

然后,生成的类实际上是一个符合 JSR-330 的可注入类,您可以将其注入到依赖关系图中(在 Dagger 或 Guice 中),它将为您创建这些对象,将调用堆栈状态与提供的依赖项混合在一起适当地。

您可以注入上述 Just-In-Time,也可以通过@Provides方法在您闲暇时。

您甚至可以让工厂实现工厂接口,然后简单地将两者绑定在 dagger 模块中,如下所示:

@AutoFactory(implementing = MyFactoryInterface.class)
public class ImageDownloader {
  // ... otherwise as above...
}

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

寻找 Dagger 辅助注射的示例 的相关文章

随机推荐

  • Android 软键盘先显示数字视图

    我的应用程序上有一个登录屏幕 它接受 CPF 作为登录名 CPF 是每个巴西公民都有的唯一号码标识 例如 10546819546 但它也可以接受护照号码作为登录名 并且上面可能有字母 我的问题是我希望键盘在弹出时在默认字母表之前显示数字 符
  • 如何解决 npm install 中的身份验证错误?

    在我的 package json 中 我有一个名为 somerepo git 的私人存储库 现在我通过 maven 在 buildserver bamboo 上运行 npm install 并收到此错误 ERROR npm ERR Comm
  • Rails 命名空间与嵌套资源

    假设我的应用程序有两个模型 Foo 和 Bar Foo 可选地属于 Bar 现在我可以查看单个 Foo 或者搜索特定的 Foo FoosController 会处理所有这些 我的网址是这样的 foos 1 and foos new 有时我想
  • php:不知从何而来的空行

    我有奇怪的错误 不知道如何解决它而不浪费太多时间 我的控制器中有一个方法 应该使用以下方法返回 xml header Content type text xml header Content Disposition attachment f
  • CQRS - 读取端的事件重播

    我读过几篇关于 CQRS 的博客 它们都解释说 在写入端 事件会持久保存在事件存储中 并且根据请求 事件将被检索并聚合重播 我的问题是为什么读取端不需要聚合事件重播 因为您的读取端不使用聚合 读取端实现为投影 它根据聚合发出的事件流计算当前
  • 设计如何覆盖 send_confirmation_instructions

    我正在尝试重写方法 send confirmation instructions 如下所示 http trackingrails com posts devise send confirmation mail manually or del
  • Serilog - RollingFile Sink 不会根据日期和大小滚动文件

    我正在使用 Serilog RollingFile Sink 但它将一天的所有数据存储在一个文件中 在我的应用程序中 一天写入 1 GB 日志 所以我想根据日期和大小滚动日志文件 如何配置 RollingFile Sink 根据日期和大小滚
  • 小于函数取消引用指针

    在某些情况下 STL 容器中有指针 并且小于比较不应通过指针进行 而应通过所指向的对象进行 一个简单的例子是一个应按实数排序的向量 目前我用以下方法解决这个问题 template
  • 将 jsonwebtoken 与 angular-cli 应用程序一起使用时出错

    我有一个 angular2 应用程序 它使用角度 cli https github com angular angular cli 20angular cli用于脚手架和其他任务 但现在我不能使用jsonwebtoken https git
  • 有向图的并查/不交集数据结构

    我正在寻找一个高效的联查 aka 不相交集 https en wikipedia org wiki Disjoint set data structure 我的数据结构有向图 https en wikipedia org wiki Dire
  • 获取符合某些条件的 Pandas DataFrame 的列和行索引对

    假设我有一只熊猫DataFrame喜欢跟随 这些值基于距离矩阵 A pd DataFrame 1 0 0 8 0 6708203932499369 0 6761234037828132 0 7302967433402214 0 8 1 0
  • libusb 和轮询/选择

    我正在使用 Linux 操作系统 想知道是否有任何文件描述符可以轮询 选择 当数据等待从 USB 设备读取时会触发这些文件描述符 我也在使用 libusb 库 但尚未找到可以使用的文件描述符 Use libusb 的轮询函数 http li
  • AES加密结果只有部分数据正确(使用mcrypt lib)

    我从以下位置下载了 AES 加密的示例代码https gist github com 2436364 https gist github com 2436364我修改了部分源代码以满足我的项目要求 如下 include
  • 如何创建服务总线触发webjob?

    我检查doc https learn microsoft com en us azure app service webjobs sdk how to service bus trigger configuration version 3x
  • 猴子修补@property

    是否有可能对 a 的值进行猴子修补 property我无法控制的类的实例 class Foo property def bar self return here be dragons f Foo print f bar baz f bar
  • :: 右侧的非法标记

    我有以下模板声明 template
  • 如何阻止猴子的疯狂行为?

    我正在使用 Monkey 工具来运行我的 Android 应用程序的测试 例如 我可能会执行如下所示的运行 adb shell monkey p com myapp v 10000 然而 如果我改变主意并需要取消测试 似乎没有办法不需要等待
  • YII 使用 gzip 压缩应用程序输出

    下面的代码有两个事件 有什么好处 它实际上在做什么 require once yii app Yii createWebApplication config Yii app gt onBeginRequest function event
  • Gradle 在 Android Studio 中应用插件(导航栏的 safeargs)

    我正在尝试学习 Android studio 并遵循官方教程 但在有关 Gradle 的部分遇到了障碍 因为该指南似乎已经过时了 指南是here https developer android com codelabs build your
  • 寻找 Dagger 辅助注射的示例

    From 匕首讨论 https groups google com forum topic dagger discuss QgnvmZ dH9c 我有一个类 它从对象图中获取一些依赖项 并在运行时从调用者获取其他依赖项 public cla