In guice is there a difference between @provides and bind()?

Ben Glasser picture Ben Glasser · Dec 15, 2014 · Viewed 7k times · Source

I am wondering what the difference is between using @provides on a method and using bind() in my guice modules.


I usually override AbstractModule.configure() and bind all my implementations to my interfaces like this:

public class MyModule extends AbstractModule
{
  @Override
  protected void configure()
  {
    this.bind(myIface.class).to(myIfaceImpl.class);
    this.bind(myOtherIface.class).to(myOtherIfaceImpl.class).asEagerSingleton();
  }
  ...
}

However, I have noticed a pattern in the codebase I'm currently working with where implementations aren't bound explicitly they are being returned from providers like this:

public class MyModule extends AbstractModule
{
  @Provides
  @Singleton
  myIface iFaceProvider()
  {
    return new myIfaceImpl();
  }
  ...
}

Is there a reason to prefer one over the other? Are there cases that force a particular method?

Answer

Tavian Barnes picture Tavian Barnes · Dec 15, 2014

If you do

bind(MyInterface.class).to(MyImplementation.class)

Guice creates the instance for you. This enables certiain things like AOP. If you do

@Provides
MyInterface provideMyInterface() {
    return new MyImplementation();
}

then Guice didn't create the instance so AOP won't work. Also, it requires an accessible constructor for MyImplementation. Generally, this form is only used when you can't edit MyImplementation to make it Guice-compatible.

There's a third form:

@Provides
MyInterface provideMyInterface(MyImplementation impl) {
    return impl;
}

which is almost totally equivalent to the bind(...).to(...) form. It is commonly used in frameworks like Dagger that do not have the bind syntax.