如何在Guice中创建可选绑定?

时间:2010-06-24 18:29:14

标签: java dependency-injection guice

这是我的客户:

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

有时候不需要Service,我们知道JVM启动时的信息(即绑定器运行之前)。 如何使绑定可选?如果我根本没有指定绑定,它会尝试新建服务(并且因为没有零参数构造函数而失败:“在package.Client.service(Service.java:40)注入时出错:可能在package.Service。“)中找不到合适的构造函数,我不能这样做:

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

因为Guice似乎不允许空值。有什么想法吗?

3 个答案:

答案 0 :(得分:7)

您使用的是Guice 2.0吗?我已经尝试了这两个,Service是一个接口(服务字段总是null),如果它不能用JIT创建一个新实例,它就是一个类(null绑定,如果它可以的实例)。两者看起来都像你期望的那样。

在这两种情况下,我都没有使用类似bind(Service.class).toInstance(null)的绑定。如果这样做,那么您需要确保Service的所有注入点都指定它们允许null。这可以通过使用任何名为@Nullable的注释注释注入点来完成(您可以自己创建或使用现有注释):

class Client {
    @Inject @Nullable Service service;
}

答案 1 :(得分:3)

如果要存在绑定可选项,可以使用@Inject(optional = true)进行字段和方法注入。对于构造函数和其他参数类型注入,必须使用辅助类,例如:

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

请注意,上述内容不允许注入null,因此Foo#hello永远不会返回null。如果您确实要允许null,只需添加@Nullable注释即可。请记住,除非您为String提供了绑定(对null,否则为其他),否则以下代码将失败:

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

答案 2 :(得分:2)

我无法重现此行为。当我运行此示例代码时,注入器创建并且可选注入不满意。该程序打印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);
  }
}

您是否可以在JUnit测试用例中重现此问题并将其提交给Guice issue tracker