Tamas
Tamas

Reputation: 3442

How to inject the default Guice Provider into my custom Provider?

If I create a provider and bind it to a class, like this

bind(MyClass.class).toProvider(MyClassProvider.class)

then Provider<MyClass> automatically be bound to MyClassProvider. That's a problem if you want to inject a Provider<MyClass> into MyClassProvider, like this:

@Inject
public MyClassProvider(Provider<MyClass> provider)

I want to inject the default Guice provider into my provider so I can easily create new instances inside my custom provider. How to do that?

Upvotes: 4

Views: 5535

Answers (1)

Michael Lloyd Lee mlk
Michael Lloyd Lee mlk

Reputation: 14661

You will need to use a binding annotation on one of the two. If you don't mind the users of MyClass being annotated it is quite easy.

public class AccountTest {

   @Test
   public void test() {
       Injector injector = Guice.createInjector(new AbstractModule() {

           @Override
           protected void configure() {
               bind(MyClass.class).annotatedWith(Names.named("MYPROVIDER")).toProvider(MyClassProvider.class);
           }
       });
       MyClassUser user = injector.getInstance(MyClassUser.class);

       assertTrue(user.get().myProvider); // Shows if was created via my provider or the Guice provider.
   }
}

class MyClassUser {
    Provider<MyClass> provider;

    @com.google.inject.Inject
    public MyClassUser(@Named("MYPROVIDER") Provider<MyClass> provider) {
        this.provider=  provider;
    }

    MyClass get() {
        return provider.get();
    }
}

class MyClass {
    boolean myProvider = false;
}

class MyClassProvider implements Provider<MyClass> {
    Provider<MyClass> provider;

    @com.google.inject.Inject
    public MyClassProvider(Provider<MyClass> provider) {
        this.provider=  provider;
    }

    @Override
    public MyClass get() {
        MyClass c = provider.get();
        c.myProvider = true;
        return c;
    }

    public String toString() {
        return "Our provider";
    }
}

If you don't want the users of MyClass to use a named provider the only way I've been able to get it to work was to extend MyClass and have MyClassProvider require a "MyClass2" Provider. As a solution it smells, but worked (rather than pollute this answer with a bad answer, you can find the code on this gist).

You may be able to do this with with private modules or child modules (as it is a variant on the Robot Legs problem) but I've been unable to work out how to do this.

Upvotes: 4

Related Questions