views:

34

answers:

1

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.

+2  A: 

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);
    }
Jesse Wilson
I guess that would do the job albeit one needs to plan what goes into what module, so that things are in separate modules with the right one being replacable at will.
mP
What are your comments about rebuilding an Injector from scratch by copying over all bindings from the original (skipping the in built bindings for c.g.i.Injector.class). Are there any disadvantages w/ this approach over the cascade and merging injection of createChildInjector ?
mP
Copying bindings from one module to another doesn't really work. At a minimum, all scopes would be reset, violating your singleton requirement.
Jesse Wilson