开发者

How do I make an optional binding in Guice?

Here is my client:

class Client {
    @Inject(optional=true) Service service;
}

Sometimes that Service isn't needed, and we know that information when the JVM starts (i.e before the binder is run). How do I make the binding optional? If I don't specify a binding at all it tries to new the Service (and fails because there is no zero-argument constructor: "Error while injecting at package.Client.service(Service.java:40): Could not find a suitable constructor in package.Service."), and I can开发者_StackOverflow社区't do:

binder.bind(Service.class).toInstance(null);

because Guice seems to disallow nulls. Any ideas?


Are you using Guice 2.0? I've tried this both with Service being an interface (service field is always null) and with it being a class (null if it can't create a new instance with a JIT binding, an instance if it can). Both seem like what you'd expect.

In neither case did I use a binding like bind(Service.class).toInstance(null). If you do this, then you need to make sure that all injection points for Service specify that they allow it to be null. This can be done by annotating the injection point with any annotation called @Nullable (you can make your own or use an existing one):

class Client {
    @Inject @Nullable Service service;
}


If you want to make the existence of a binding optional you can use @Inject(optional = true) for field and method injections. For contructor and other parameter type injections, you must use a helper class, for example:

class Foo {
  public String hello(Helper helper) {
    return Helper.string;
  }
  private static final class Helper {
    @Inject(optional = true) public String string = "";
  }
}

Note that the above doesn't allow null to be injected, so Foo#hello will never return null. If you do want to allow null, simply add the @Nullable annotation. Keep in mind that code like the following will fail unless you've provided a binding (to null, if nothing else) for String:

class Bar {
  @Inject @Nullable public String hello(@Nullable String string) {
    return string;
  }
}


I couldn't reproduce this behavior. When I run this example code, the injector creates and the optional injection is left unsatisfied. The program prints null:

public class OptionalInjections {

  static class Service {
    public Service(Void v) {} // not injectable
  }

  static class Client {
    @Inject(optional = true) Service service;
  }

  public static void main(String[] args) {
    Injector i = Guice.createInjector();
    Client client = i.getInstance(Client.class);
    System.out.println(client.service);
  }
}

Could you reproduce this in a JUnit test case and submit it to the Guice issue tracker?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜