Search code examples
javadependency-injectionguice

Guice: Using @Named to create object


Using Guice, if I have

@Inject @Named("light")
Color light;

I can use

bind(Color.class).annotatedWith(Names.named("light"))
    .toInstance(new Color("white"));

to bind it to white color if Color constructor only requires color name.

But how can I do it if Color constructor also requires objects which are created by Guice? For example:

@Inject
public Color(ColorSet colorset, String colorName) {...}

where colorset is create at runtime by Guice and in not available in configure(){...}.

I would like to do it without:

  • creating a class/subclass for each color that I need to inject (like WhiteColor)
  • using reflection directly in my code
  • changing my classes to use ColorFactoy factory; factory.get("light"); instead of @Named("light") Color light;

Solution

  • The best way to do this is not with a factory but with @Provides methods. My company uses Guice very, very extensively, and requestInjection is always considered a bad idea because it can easily set up a very fragile graph of implicit dependencies.

    Here's what it should look like:

    public class FooModule extends AbstractModule {
      protected void configure() {
        // do configuration
      }
    
      @Provides
      @Named("white")
      Color provideWhiteColor(ColorSet colorSet) {
        return colorSet.white(); // or whatever
      }
    
      @Provides
      @Named("black")
      Color provideBlackColor(ColorSet colorSet) {
        return colorSet.black(); // or whatever
      }
    
      // etc
    }