Guice:提供者中的注入器

nes*_*rbu 4 provider task guice executor

我知道通常注入器应该在所有应用程序中仅使用一次(在启动时)。但我有以下用例。我为 Executor 注入任务实现,然后在该任务中我有FileHandler每次都必须实例化的依赖项(可以说)。我知道方法是注入提供程序(可以说FileHandlerProvider),每次请求时都会返回新实例。问题是FileHandler它自己有很多依赖项(可以说ParserOutputPrinter......)。现在,这些每次也需要新的实例(因为实现可能有一些状态,例如计数器,并且在下一个线程运行时重用同一实例将是一个问题)。问题是,注入提供程序后,会重用提供程序的相同实例,因此FileHandler总是使用 sameParser和创建 new OuputPrinter。解决方案可能是再次注入ParserProvider andOutputPrinterProvider而不是 Parser 和OuputPrinterin FileHandlerProvider,但这是不对的,它很快就会变得太复杂,因为有更多的依赖项。我现在看到的唯一简单的解决方案可能是使用 Injector in FileHandlerProvider,它将返回新实例FileHandler(以及依赖项的新实例)。或者在这种情况下也许还有另一种更优雅的解决方案?

Col*_*inD 5

您应该仅FileHandler使用默认范围(即无范围)绑定及其依赖项。然后每次需要新实例时注入Provider<FileHandler>并使用它。由于没有范围,因此每次都需要创建一个新实例...并且由于其依赖项也没有范围,因此每次也需要创建每个实例的新实例。它应该按照您想要的方式工作。get()FileHandlerFileHandlerget()FileHandler

我认为您(可能)在这里缺少的是您不需要自己编写任何这些提供程序......只需注入Provider<FileHandler>,Guice 就会为您完成这一切。

编辑:这是我编写的一个小类,它演示了每次创建该类的实例时都会创建新的类的依赖关系。

public class Test {
  public static void main(String[] args) {
    Injector injector = Guice.createInjector();
    injector.getInstance(Test.class);
  }

  @Inject public Test(Provider<FileHandler> fileHandlerProvider) {
    FileHandler fileHandler1 = fileHandlerProvider.get();
    FileHandler fileHandler2 = fileHandlerProvider.get();

    System.out.println("fileHandler1 == fileHandler2? " + 
        (fileHandler1 == fileHandler2));
    System.out.println("fileHandler1.parser == fileHandler2.parser? " + 
        (fileHandler1.parser == fileHandler2.parser));
    System.out.println("fileHandler1.print == fileHandler2.printer? " + 
        (fileHandler1.printer == fileHandler2.printer));
  }

  private static class FileHandler {
    private final Parser parser;
    private final OutputPrinter printer;

    @Inject private FileHandler(Parser parser, OutputPrinter printer) {
      this.parser = parser;
      this.printer = printer;
    }
  }

  private static class Parser {
  }

  private static class OutputPrinter {
  }
}
Run Code Online (Sandbox Code Playgroud)

运行时,此代码打印:

文件处理程序1 == 文件处理程序2?错误的
fileHandler1.parser == fileHandler2.parser?错误的
fileHandler1.print == fileHandler2.printer?错误的

这表明不仅FileHandler每次都会创建一个新实例,而且每次也会创建新Parser实例OutputPrinter并注入到其中。FileHandler