2016-12-06 3 views
1

Скажем, у меня есть модуль с ThirPartyModule третьей стороной, которая связывает много компонентов, которые можно затем использовать в моем приложении:Guice: Как настроить привязки стороннего модуля?

Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule()); 

Если я хочу изменить классы реализации, используемые для некоторых привязок в этом модуле, какой лучший подход?

Например, скажем ThirPartyModule выполняемое, что связывание:

bind(WidgetInterface.class).to(DefaultWidgeImpl.class).in(Scopes.SINGLETON); 

, и я хочу, чтобы иметь возможность изменить DefaultWidgeImpl класс для MyWidgetImpl класса. Я знаю, что могу использовать переопределяющий модуль и просто перепроверять ключ WidgetInterface. Но что, если ThirPartyModule связывает много вещей, использующих то же самое Внедрение виджета? Возможно, я не хочу переписывать каждого из них!

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

Я думаю ThirPartyModule может сначала создать геттер для класса реализации:

bind(WidgetInterface.class).to(getWidgetImpClass()).in(Scopes.SINGLETON); 

protected Class<? extends WidgetInterface> getWidgetImpClass() { 
    return DefaultWidgeImpl.class; 
} 

, а затем приложение может переопределить getWidgetImpClass() метод:

Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule() { 
    @Override 
    protected Class<? extends WidgetInterface> getWidgetImpClass() { 
     return MyWidgetImpl.class; 
    } 
}); 

я хотя о прохождении класса реализации к конструктору модуля:

Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule(MyWidgetImpl.class)); 

Хотелось бы узнать, есть ли принятый шаблон для настройки таких сторонних модулей? Предположим, что может спросить модули, которые должны быть написаны определенным образом, если это поможет им настраиваться.

ответ

2

Вот как я бы это сделать:

public class ThirdPartyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     // CoolWidget -- 
     //    \ 
     //    > WidgetInterface -> DefaultWidgetImpl 
     //   /
     // AwesomeWidget 

     OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class) 
       .setDefault() 
       .to(DefaultWidgetImpl.class); 

     bind(CoolWidget.class).to(WidgetInterface.class); 
     bind(AwesomeWidget.class).to(WidgetInterface.class); 
     // etc. 
    } 
} 

public class MyAppModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class) 
       .setBinding() 
       .to(CustomWidgetImpl.class); 
    } 
} 

Делая все переплеты идут косвенно через ключ WidgetInterface, вам только нужно переопределить один связывающую.

+0

Wow, я должен признать, что я даже не знал 'OptionBinder', это будет удобно действительно ... Спасибо! – electrotype

+0

Я не думаю, что синглтон имеет какое-либо отношение к '@Named (" default ")'. Если 'CustomWidgetImpl' должен быть singleton, то пометьте его' @ Singleton' или сделайте '.in (Singleton.class)'. –

+0

Независимо от того, вы, вероятно, можете обойтись без '@Named (" default ")'. Это будет просто '{CoolWidget, AwesomeWidget} -> WidgetInterface -> DefaultWidgetImpl'. –