Guice:提供者中的注射器

时间:2011-01-22 16:18:33

标签: task guice provider executor

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

1 个答案:

答案 0 :(得分:4)

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

我认为你(也许)在这里缺少的是你自己不需要写任何这些提供者......只需注入Provider<FileHandler>而Guice会为你做这一切。 / p>

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

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 {
  }
}

运行时,此代码打印:

fileHandler1 == fileHandler2? false
fileHandler1.parser == fileHandler2.parser? false
fileHandler1.print == fileHandler2.printer? false

这表明每次都会创建一个新的FileHandler实例,每次创建新的ParserOutputPrinter个实例并将其注入FileHandler