2010-09-16 2 views
1

У меня есть основное приложение Java с несколько сложными аргументами командной строки. Эти аргументы в настоящее время обрабатываются классом CommandLineArgumentProcessor. Вот как выглядит мой текущий код:Лучший способ поменять привязки Guice на основе параметра командной строки

public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new ConfigModule(), new WorkModule(), new ReportModule); 
    injector.getInstance(I_CommandLineArgumentProcessor.class).processArguments(args); 
    //Its not until here that I know if I should stub or not with this implementation 
    ... 
} 

Теперь я реализую способ отсечения некоторых классов для тестирования системы. Для этого мне нужно поменять некоторые привязки, которые использует Guice. Затем в командной строке я укажу некоторые флаги для включения/выключения воспроизведения различных функций. Однако моя проблема заключается в том, что аргументы не обрабатываются до тех пор, пока не будет создан инжектор.

Должен ли я иметь отдельную логику для обработки моих обрезных флагов до создания инжектора, а затем условно создать соответствующий инжектор? Я не решаюсь на этот подход, потому что он делит логику обработки аргументов командной строки на две области кода. Или есть другой (подходящий) способ заставить Guice заменить различные объекты/поддеревья на графе объектов после создания инжектора? Или у меня есть один инжектор для процессора командной строки, а затем создать еще один для остальной части модулей?

ответ

3

Связывание инжектора является неизменным после его создания (хотя сами привязки могут быть динамическими). Я бы предложил сначала создать инжектор, который связывает только то, что вам нужно для обработки командной строки. Затем выполните обработку командной строки, получите флаги и используйте их при создании другого инжектора, который будет использовать фактическое приложение. Если есть вещи, которые вам нужно связать, чтобы иметь возможность выполнять обработку в командной строке, чтобы остальная часть приложения также нуждалась в этом, вы могли бы просто создать второй инжектор в качестве дочернего инжектора первого.

Есть, вероятно, некоторые другие странные вещи, которые вы можете сделать, такие как имеющая изменяемый синглтон, что флаги командной строки устанавливаются на и с использованием методами поставщика, которые зависят от этого объекта:

@Provides 
protected Foo provideFoo(Config config) { 
    return config.isStubFoo() ? new StubFoo() : new RealFoo(); 
} 

Но я думаю, первый подход намного предпочтительнее.

+0

Спасибо Колин. Первый подход нескольких инжекторов вырос на меня, и я думаю, что это будет тот, который я использую. Как новичок в Guice, у меня есть достаточно «странных вещей», чтобы справиться, так что я сохраню это просто на данный момент! Но я думаю, что я понимаю, что вы пример провайдера. –

1

Рассматриваете ли вы использование детских инжекторов? Из вашего примера, похоже, что вам нужна только корневая инъекция, чтобы получить экземпляр I_CommandLineArgumentProcessor. Без дополнительного контекста я бы предложил указать инжектор корня с минимальными привязками, необходимыми для создания I_CommandLineArgumentProcessor.

Затем вы можете использовать свой I_CommandLineArgumentProcessor совместно с каким-либо другим впрыснутым классом провайдера, чтобы вернуть вам модули, которые вы используете, чтобы передать метод createChildInjector.

+0

Спасибо alpian, я раньше не слышал о детских инъекциях, но теперь, когда я прочитал API, я думаю, что понимаю, что они делают. Поскольку я не требую I_CommandLineArgumentProcessor за пределами первоначального вызова, я думаю, что я буду придерживаться создания нового инжектора как самого чистого решения для меня. Но спасибо, что научи меня чему-то новому :) –