java 如何在 Guice 中进行可选绑定?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3112853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:25:33  来源:igfitidea点击:

How do I make an optional binding in Guice?

javadependency-injectionguice

提问by gubby

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't do:

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

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

because Guice seems to disallow nulls. Any ideas?

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

回答by ColinD

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

您在使用 Guice 2.0 吗?我已经尝试过Service作为一个接口(服务字段总是null)和一个类(null如果它不能用 JIT 绑定创建一个新实例,如果可以的话,一个实例)。两者似乎都符合您的预期。

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 Servicespecify 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):

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

class Client {
    @Inject @Nullable Service service;
}

回答by gubby

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:

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

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 nullto be injected, so Foo#hello will never return null. If you do want to allow null, simply add the @Nullableannotation. Keep in mind that code like the following will fail unless you've provided a binding (to null, if nothing else) for String:

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

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

回答by Jesse Wilson

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:

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

您能否在 JUnit 测试用例中重现这一点并将其提交给Guice 问题跟踪器