2011-10-05 4 views
3

У меня есть следующая проблема:Guice: инъекции во время выполнения/связывания в командной строке

@Inject 
    MyClass(Service service) { 
     this.service = service; 
    } 

    public void doSomething() { 
     service.invokeSelf(); 
    } 

У меня есть один модуль

bind(service).annotatedWith(Names.named("serviceA").to(ServiceAImpl.class); 
bind(service).annotatedWith(Names.named("serviceB").to(ServiceBImpl.class); 

Теперь моя проблема, я хочу, чтобы позволить пользователю динамически выбирать инъекции на основе времени выполнения через параметр командной строки.

public static void Main(String args[]) { 
    String option = args[0]; 
    ..... 
} 

Как я могу это сделать? Должен ли я создавать несколько модулей только для этого?

ответ

6

Если вам нужно многократно выбирать во время выполнения, реализация которого для использования mapbinder очень уместна.

У вас есть конфигурация как:

@Override 
protected void configure() { 
    MapBinder<String, Service> mapBinder = MapBinder.newMapBinder(binder(), String.class, Service.class); 
    mapBinder.addBinding("serviceA").to(ServiceAImpl.class); 
    mapBinder.addBinding("serviceB").to(ServiceBImpl.class); 
} 

Затем в коде просто впрыснуть карту и получить правильное обслуживание на основе вашего выбора:

@Inject Map<String, Service> services; 

public void doSomething(String selection) { 
    Service service = services.get(selection); 
    // do something with the service 
} 

Вы даже можете заполнить форсунку с выбранную услугу, используя custom scopes.

4

Я думаю, что вы на самом деле хотите сделать что-то больше, как это:

public class ServiceModule extends AbstractModule { 
    private final String option; 

    public ServiceModule(String option) { 
    this.option = option; 
    } 

    @Override protected void configure() { 
    // or use a Map, or whatever 
    Class<? extends Service> serviceType = option.equals("serviceA") ? 
     ServiceAImpl.class : ServiceBImpl.class; 
    bind(Service.class).to(serviceType); 
    } 
} 

public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new ServiceModule(args[0])); 
    // ... 
} 
3

@ColinD имеет хороший подход. Я мог бы предложить

public static void main(String[] args) { 
    Module m = "serviceA".equals(args[0]) ? new AServiceModule() : new BServiceModule(); 
    Injector injector = Guice.createInjector(m); 
    // ... 
} 

Основная идея (в обоих ответов), если вы можете сделать свой выбор, прежде чем инжектор будет построен, вы всегда должны выбрать, чтобы сделать это.

В качестве стиля я хотел бы свести количество логики внутри модуля к минимуму; но опять же, только вопрос стиля.

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