Guice: injector in provider

I know that usually the injector should be used only once in all applications (at startup). But I have the following use case. I am implementing a run task for Executor, and then inside this task I have a dependency (say FileHandler) that needs to be created every time. I know that I need to implement a provider (say, FileHandlerProvider) that will return a new instance every time it is requested. The problem is that it FileHandlerhas many dependencies on its own (say Parser,OutputPrinter...). Now they also need a new instance each time (because the implementation may have some kind of state, such as counters, and the next time you reuse the same instance). The fact is that after the provider is entered, the same provider instance is reused, so a new FileHandlerone is always created with the same Parserand OuputPrinter. The solution might again introduce ParserProviderboth OutputPrinterProviderinstead of Parser and OuputPrinterin FileHandlerProvider, but it is not, it will soon become too complicated because there are more dependencies. The only simple solution that I see now is to use Injector in FileHandlerProvider, which will return a new instanceFileHandler(and new instances of dependencies). Or maybe in this situation there is another elegant solution?

+3
source share
1 answer

You should just bind FileHandlerall its dependencies with the default value (i.e. without scope). Then enter Provider<FileHandler>and use it get()every time you need a new instance FileHandler. Since it FileHandlerdoes not have a scope, each time it get()is called, a new instance is created FileHandler... and since its dependencies also do not have a scope, each instance of each of them must be created every time. It should work the way you want.

I think the thing you're (possibly) missing here is that you don't need to write any of these providers yourself ... just type Provider<FileHandler>in and Guice will do it all for you.

: , , .

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, Parser OutputPrinter FileHandler .

+4

Source: https://habr.com/ru/post/1787163/


All Articles