Home > database >  Guice module provides singleton with two bindings?
Guice module provides singleton with two bindings?

Time:10-26

I'm very new to Guice (and I'm much more proficient in languages other than Java), but essentially what I want to do is edit some code to convert something like this:

public class AutomobileModule extends AbstractModule {
   @Provides
   @Singleton
   Automobile getCar(final AutomobileFactory automobileFactory) {
      return automobileFactory.createAutomobile("Car");
   }

   @Provides
   @Singleton
   AutomobileFactory getAutomobileFactory(final AutomobileConfiguration automobileConfiguration) {
      return new AutomobileFactory(automobileConfiguration);
   }

   @Provides
   @Singleton
   AutomobileConfiguration getAutomobileConfiguration() {
      return new AutomobileConfiguration();
   }
}

by adding

public class AutomobileModule extends AbstractModule {
   <...SNIP...>

   @Provides
   @Singleton
   Automobile getTruck(final AutomobileFactory automobileFactory) {
      return automobileFactory.createAutomobile("Truck");
   }
}

However, if I try this, I get "A binding to... was already configured at" error. So what's the correct way to share dependencies this way? Or do people usually just create multiple factories, etc, in cases like this.

CodePudding user response:

As you configured it, Guice can only decide by the type which object to inject and you have two methods that provide Automobile. The methods name is irrelevant.

You will have to specify which method provides which kind of Automobile, you could do this by adding annotations @Named("Car") and @Named("Truck") to your methods.

To get exactly the right kind of Automobile injected, you have to specify that same annotation (@Named...) also at the place where you get it injected.

Your module would then look something like this:

public class AutomobileModule extends AbstractModule {
   @Provides
   @Singleton
   @Named("Car")
   Automobile getCar(final AutomobileFactory automobileFactory) {
      return automobileFactory.createAutomobile("Car");
   }

   @Provides
   @Singleton
   AutomobileFactory getAutomobileFactory(final AutomobileConfiguration automobileConfiguration) {
      return new AutomobileFactory(automobileConfiguration);
   }

   @Provides
   @Singleton
   AutomobileConfiguration getAutomobileConfiguration() {
      return new AutomobileConfiguration();
   }

   @Provides
   @Singleton
   @Named("Truck")
   Automobile getTruck(final AutomobileFactory automobileFactory) {
      return automobileFactory.createAutomobile("Truck");
   }
}

See the official user guide for more information and this accepted SO answer (together with the question) for a better example than in the user guide.

  • Related