当前位置: 首页 > 面试题库 >

寻找Dagger辅助注射的例子

阎丰
2023-03-14
问题内容

来自dagger-discuss @:

我有一个类,它从对象图中获取一些依赖关系,而在运行时从调用者那里获取其他依赖关系。

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()方法。

如您所见,这很冗长且冗长。它还有很多重复和样板。使用来注释字段本身存在一些障碍@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(代码生成的辅助注入),AutoValue(代码生成的自定义值)的项目中创建了一个名为AutoFactory(http://github.com/google/auto)的东西。类型)和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中),它将为您创建这些对象,将调用堆栈状态与提供的依赖项混合在一起适当地。

您可以注入上述“即时”,也可以@Provides在闲暇时通过某种方法提供。

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

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

@Module(...)
class MyModule {
  @Provides MyFactoryInterface factoryImpl(ImageDownloaderFactory impl) {
    return impl;
  }
}


 类似资料:
  • 我是Guice的新手,所以我试图理解AssistedInject。我有一个非常简单的项目: 我要注入的类: 带辅助注射的类别: 工厂 主类: 但它仍然不起作用,我不明白,我错在哪里?

  • 问题内容: 使用Google Guice或Gin,我可以指定不受依赖项注入框架控制的参数: 辅助参数是在创建实例时指定的。 SomeClassA的实例是从对象图中获取的,而SomeClassB的实例是从运行时的调用者中获取的。 在Dagger中有类似的方法吗? 问题答案: 因为工厂是一种单独的样板,可以进行优化(请参阅此处的邮件列表讨论),所以Dagger将其留给了姊妹项目AutoFactory。

  • 我已经使用google-guice和辅助注射机制有一段时间了。因为我在scala,刚刚发现scala-guice,我也对使用它感兴趣。但是我对如何使用辅助注射感到困惑。没有使用辅助注射的例子。 因此,我的问题是:是否可以使用scala guice辅助注射,如果可以,请提供一个简单的例子? 此外,对于google-guice,我使用以下库:javax.inject.jar、guice-3.0.jar

  • 我正在使用Guice Assisted Inject库为我建立一个工厂。我目前的设置如下: 这迫使我使用< code > factory . create controller(first,factory . create second(first))显式创建一个< code>SecondDep。是否可以更改我的绑定,这样我就可以简单地执行< code > factory . create con

  • 我在实施辅助注射时遇到了错误。 辅助注射一直有效,直到我引入了另一个名为管理器的类,它依赖于辅助类。经理想要使用代码在构建喷油器图时中断。它没有更进一步。 直觉上,我理解当对象A得到帮助时,那么B(依赖于A)实际上也通过A得到了隐含的帮助。 请注意,我检查过了。我想像ColinD这样的人肯定知道答案如何使用Guice的AssistedInject?如何将辅助注入类绑定到接口? 出于好奇,有没有好的

  • 我目前正在我的应用程序中使用Guice。然而,我发现自己大多使用辅助注入,因为有一个注入对象链,它们都依赖于程序的输入。因此几乎所有的东西都是辅助注射的。 例如,A需要B,B需要c,c需要Z,Z需要来自命令行的输入。最后我感觉一切都将被辅助注射。因此,鉴于我坚持使用它,我想确定我使用它是正确的。 我个人觉得写我自己的工厂也一样好。此外,除了同样的优点之外,我还可以进一步将我所讨论的对象的创建限制在