【问题标题】:Guice: injector in providerGuice:提供程序中的注入器
【发布时间】:2011-01-22 16:18:33
【问题描述】:

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

【问题讨论】:

    标签: task guice provider executor


    【解决方案1】:

    您应该将FileHandler 及其依赖项全部绑定到默认范围(即无范围)。然后注入Provider<FileHandler> 并在每次需要新的FileHandler 实例时使用它的get()。由于FileHandler 没有范围,每次调用get() 时都需要创建一个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 {
      }
    }
    

    运行时,此代码打印:

    fileHandler1 == fileHandler2?错误的
    fileHandler1.parser == fileHandler2.parser?错误的
    fileHandler1.print == fileHandler2.printer?假的

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

    【讨论】:

    • 嗨,感谢您的回答,但问题是即使我不手动创建提供程序 - FileHandler 的依赖项也是相同的重用实例。这可能是因为 Task 只创建一次,然后它注入了提供程序(也只有一个实例),提供程序创建了 FileHandler 的新实例,但始终使用相同的 FileHandler 依赖项实例,因为它们在创建时通过 guice 注入提供程序。所以我想没有其他办法,只需在提供程序中使用注入器...
    • @Ignas:我不确定你的意思。依赖项不应该被重用,除非它们有一些导致它们被重用的范围,或者你正在做一些专门导致它们被重用的事情。请参阅我的示例。
    • 哎,是我调试的时候搞错了。这是工作。谢谢! :)
    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多