Guice: инжектор в провайдере - PullRequest
3 голосов
/ 22 января 2011

Я знаю, что обычно инжектор должен использоваться только один раз во всех приложениях (при запуске). Но у меня есть следующий вариант использования. Я внедряю реализацию задачи для Executor, а затем внутри этой задачи у меня есть зависимость (скажем, FileHandler), которая должна создаваться каждый раз. Я знаю, что способ заключается в том, чтобы внедрить провайдера (скажем, FileHandlerProvider), который будет возвращать новый экземпляр каждый раз при запросе. Проблема в том, что FileHandler имеет много собственных зависимостей (скажем, Parser, OutputPrinter ...). Теперь они также нуждаются в новом экземпляре каждый раз (потому что реализации могут иметь некоторое состояние, например, счетчики, и при следующем запуске потока повторное использование одного и того же экземпляра будет проблемой). Дело в том, что после введения провайдера один и тот же экземпляр провайдера используется повторно, поэтому новый FileHandler всегда создается с одинаковыми Parser и OuputPrinter. Решением может быть снова ввести ParserProvider и OutputPrinterProvider вместо Parser и OuputPrinter в FileHandlerProvider, но это просто не правильно, это слишком усложняется в ближайшее время, потому что есть больше зависимостей. Единственное простое решение, которое я вижу сейчас, может заключаться в использовании Injector в FileHandlerProvider, который будет возвращать новый экземпляр FileHandler (и новые экземпляры зависимостей). Или, может быть, есть другое более элегантное решение в этой ситуации?

1 Ответ

4 голосов
/ 22 января 2011

Вы должны просто связать FileHandler и все его зависимости с областью по умолчанию (т.е. без области). Затем введите Provider<FileHandler> и используйте его get() каждый раз, когда вам нужен новый экземпляр FileHandler. Поскольку 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? false
fileHandler1.parser == fileHandler2.parser? false
fileHandler1.print == fileHandler2.printer? false

Это показывает, что не только новый экземпляр FileHandler создавался каждый раз, новые экземпляры Parser и OutputPrinter создавались и также вводились в FileHandler каждый раз.

...