Search code examples
javadependency-injectionguicelifecycle

How to control object's lifecycle with Guice


I have Guice-injected objects which have two lifecycle methods bind() and unbind(). The method bind() is called automatically after the object is instantiated by Guice using following annotated method:

@Inject
final void autoBind() {
    bind();
}

What I want to do is to call the method unbind() on the old (current) object before a new instance of the object is created by Guice. How do I do that?

Thanks in advance!


Solution

  • First of all, I would not advise that you just annotate arbitrary methods with @Inject. Keep it to constructors, and occasionally for optional injection and/or field injection.

    What you are trying to do does sound a bit weird, and I'm not sure it's exactly what you want. Can you please provide more background on what you're trying to do because maybe a different approach is better. There are definitely some concerns here with thread safety and how you manage references.

    Based on what you described, an approach like what @meverett mentioned would probably work. If the objects you have are Foos, it would look something like this.

    // Later on be sure to bind(Foo.class).toProvider(FooProvider.class);
    final class FooProvider implements Provider<Foo> {
      private final Provider<Foo> unboundFooProvider;
    
      private Foo currentInstance;
    
      @Inject FooProvider(@Unbound Provider<Foo> unboundFooProvider) {
        this.unboundFooProvider = unboundFooProvider;
      }
    
      @Override public Foo get() {
        if (currentInstance != null) {
          currentInstance.unbind();
        }
        currentInstance = unboundFooProvider.get();
        currentInstance.bind();
        return currentInstance;
      }
    }
    

    NOTE that your @Unbound Foo provider would generate Foos without invoking any special methods. The regular FooProvider keeps track of state and deciding when to bind() and unbind() the instances. Please be careful with how you manage multiple instances and use them with multiple threads.

    Also, just to be clear: I'm using @Unbound since the methods you want to invoke are called bind() and unbind(). I'm not using "bound" in the Guice sense.

    Also note... off the top of my head I'm pretty sure Providers are treated as singletons, so maintaining state like this will work. If it didn't, you could obviously just create a level of indirection with some kind of singleton factory (but that shouldn't be necessary).