I am hoping to redefine or update some bindings within a Module which is in turn used by an Injector. I realise that Modules are immutable and once a binding is sucked and injected its definition cannot change for all practical purposes.
I would like to add/change/remove bindings while keeping singletons already living in an Injector. Changing is a simple case as one can achieve this effecct by using a Provider. However dynamically adding or removing a Key (binding definition) is a bit more tricky.
Any thoughts if this should or can be practically done.
I am thinking the best way is to recreate an injector each time an add/remove binding occurs copying definitions from the original to the new one, Any existing singletons would be redefined by toInstance rather than to implementation type etc.
Child injectors can be used to accomplish this, but it requires some setup. Child injectors will prevent long-lived bindings from depending on short-lived ones. Here's an example:
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 bindings in the forever module will last as long as that module exists. Singleton bindings in the temporary module will last as long as you're using the corresponding injector.
Warning: By default, just-in-time bindings will be created in the top-level injector. If you need a binding to be short-lived, you need to bind both the interface and the implementation in your child injector's module. That looks like this:
public void configure() {
bind(Foo.class).to(RealFoo.class);
bind(RealFoo.class);
}