2011-01-22 4 views
3

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

ответ

4

Вы должны просто привязать 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 каждый раз также.

+0

Привет, спасибо за ответ, но дело в том, что даже если я не создаю поставщиков вручную - зависимости FileHandler - это те же повторные экземпляры. Вероятно, это происходит из-за того, что Task создается только один раз, затем он вводит провайдера (также только один экземпляр), поставщик создает новый экземпляр FileHandler, но всегда использует те же экземпляры зависимостей FileHandler, поскольку они были введены в провайдер по указанию на его создание. Так что я не хочу, чтобы другого выхода не было, просто используйте инжектор в провайдере ... – nesvarbu

+0

@ Игнас: Я не уверен, что вы имеете в виду. Зависимости не следует использовать повторно, если они не имеют какой-либо области, которая заставляет их повторно использовать или вы делаете то, что специально заставляет их повторно использовать. См. Мой пример, демонстрирующий это. – ColinD

+0

Эй, это была моя ошибка, когда я отлаживал. Это работает. Благодаря! :) – nesvarbu

Смежные вопросы