Guice: создание инжекторов для общих библиотек - PullRequest
1 голос
/ 13 января 2012

Новое в Google Guice.Я хотел бы использовать его для обработки всего перехвата методов IoC и AOP для трех компонентов, которые я разрабатываю:

  • WidgetClient - приложение Swing
  • WidgetServer - небольшоеEAR, к которому клиент будет подключаться или взаимодействовать с
  • WidgetShared - JAR-файлом "commons", который содержит общие классы, используемые как клиентом, так и серверомЯ сделаю явный вызов, который может выглядеть следующим образом:
    public static void main(String[] args) {
        initGuiceInjectors();
    }
    
    private static initGuiceInjectors() {
        Guice.createInjector(mySwingAppModule);
    }
    

    mySwingAppModule определит все привязки для зависимостей приложения Swing.Я сделаю нечто очень похожее на сервере EAR.

    Когда дело доходит до библиотеки WidgetShared, я задыхаюсь, потому что у библиотеки нет единой точки входа: это просто набор пакетов, классы, интерфейсы и перечисления, которые клиент и сервер будут использовать повсеместно.

    Итак, мой первый вопрос: где мне вызвать Guice.createInjector() для WidgetShared JAR?

    Этот вопрос подчеркивает переход во второй (похожий) вопрос, поэтому я решил также сгруппировать его здесь.Кажется, чтобы (где это применимо), сохранить Module реализации на уровне пакета.Таким образом, для каждого пакета будет один Module конкрет, определяющий привязки для всех типов в этом пакете.Это улучшение по сравнению с одним монолитным Module, определяющим привязки для всего приложения.

    Итак, приведенный выше фрагмент кода (Guice.createInjector(mySwingAppModule)) на самом деле не , как мой код в конечном итоге будет выглядетькак (извините, я солгал!).

    Мой второй вопрос: Каковы "лучшие практики" для создания нескольких инжекторов?

    Я вижу, что createInjector(Module... modules) можетвозьми vararg Module аргументов.Таким образом, мне кажется, что если я захочу использовать эту лучшую практику " 1-module-per-package ", в какой-то момент мне понадобится код, который либо выглядит следующим образом:

    Guice.creatorInjector(package1Module, package2Module, package3Module,
        package4Module, package5Module, package6Module, ..., packageNModule);
    

    или, вот так:

    Guice.createInjector(package1Module);
    Guice.createInjector(package2Module);
    Guice.createInjector(package3Module);
    
    ...
    
    Guice.createInjector(packageNModule);
    

    Оба они выглядят действительно противно!Есть ли лучший способ сделать это?!?

    Заранее спасибо!

1 Ответ

4 голосов
/ 21 января 2012

Адам

В вашем вопросе есть два элемента, но оба они явно связаны. Я пойду назад, начиная со второго элемента первым.

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

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

В конце концов у вас будет что-то вроде:

public WidgetSharedLibraryModule extends AbstractModule {
  @Override protected void configure() {
    install(new WidgetSublibraryModule1());
    install(new WidgetSublibraryModule2());
    ...
  }
}

И ваш основной метод будет выглядеть так:

public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new WidgetSharedLibrary(),
        new WidgetSwingAppModule());
    WidgetSwingApp app = injector.getInstance(WidgetSwingApp.class);
    app.run();
}
...