Лучший подход к изменению (добавлению/удалению привязок) инжектора Guice при сохранении состояния

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

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

Любые мысли, если это должно или может быть практически сделано.

Я думаю, что лучший способ - воссоздавать инжектор каждый раз, когда происходит привязка добавления/удаления, копируя определения из оригинала в новый. Любые существующие синглтоны будут переопределены с помощью toInstance, а не типа реализации и т. д.


person mP.    schedule 20.06.2010    source источник


Ответы (1)


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

class ForeverModule extends AbstractModule {
  ...
}

class TemporaryModule extends AbstractModule {
  ...
}

class Main {
    public static void main(String... args) {
        Injector foreverInjector = Guice.createInjector(new ForeverModule());

        Injector injector = foreverInjector.createChildInjector(
                new TemporaryModule());
        /*
         * Do stuff with the injector as you would normally. When you
         * get bored of that injector, create a replacement injector
         * as a child of the long-lived injector.
         */
    }
}

Одноэлементные привязки в модуле навсегда будут действовать до тех пор, пока существует этот модуль. Привязки Singleton во временном модуле будут действовать до тех пор, пока вы используете соответствующий инжектор.

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

public void configure() {
    bind(Foo.class).to(RealFoo.class);
    bind(RealFoo.class);
}
person Jesse Wilson    schedule 20.06.2010
comment
Я предполагаю, что это сделает работу, хотя нужно спланировать, что входит в какой модуль, чтобы вещи были в отдельных модулях, а нужный можно было заменить по желанию. - person mP.; 20.06.2010
comment
Каковы ваши комментарии по поводу восстановления инжектора с нуля путем копирования всех привязок из оригинала (пропуская встроенные привязки для c.g.i.Injector.class). Есть ли какие-либо недостатки у этого подхода по сравнению с каскадной и слияющей инъекцией createChildInjector? - person mP.; 20.06.2010
comment
Копирование привязок из одного модуля в другой на самом деле не работает. Как минимум, все области будут сброшены, что нарушит ваше требование к синглтону. - person Jesse Wilson; 20.06.2010