java - 使用 Guice 按类型和注释检索单例

标签 java guice

我有几个类实现 interface Provider<Communication>我正在使用 Guice 和 @Named注解以根据需要绑定(bind)它们,例如:

@Singleton
public class Verizon implements Provider<Call> {
  ...
}

@Singleton
public class TMobile implements Provider<Call> {
  ...
}

bind (new TypeLiteral<Provider<Call>>() {}).annotatedWith(
  Names.named("Verizon")).to(Verizon.class);

bind (new TypeLiteral<Provider<Call>>() {}).annotatedWith(
  Names.named("TMobile")).to(TMobile.class);

是否有一种干净的方法来实现将名称作为参数的工厂,例如:

public static <C extends Communication> Provider<C> getCallProvider(C communication) {
  String providerName = communication.getProviderName();

  return [Guice's matching object for type Provider<?> and @Named = providerName];
}

我尝试使用 Injector,但 Guice 不会将泛型作为 TypeLiteral 的参数:

public <C extends Communication> Provider<C> getCommunicationProvider(C communication) {
  return injector.getInstance(Key.get(new TypeLiteral<CommunicationProvider<C>>() {},
    Names.named(communication.getProvider().getId())));
}

这会抛出:

com.google.inject.ConfigurationException: Guice configuration errors:
  1) Provider<C> cannot be used as a key; It is not fully specified.

最佳答案

提供商由 Guice 管理;当您绑定(bind)Foo时或Provider<Foo>正确的话,您应该可以请求 FooProvider<Foo>无需任何额外的工作。因此,您可能不希望这样:

bind (new TypeLiteral<Provider<Call>>() {}).annotatedWith(
  Names.named("Verizon")).to(Verizon.class);

相反,您可能想要这个:

bind(Call.class).annotatedWith(Names.named("Verizon")).toProvider(Verizon.class);

...这将让你注入(inject) @Named("Verizon") Provider<Call>还有@Named("Verizon") call 。那时您最初的请求就像这样简单:

/**
 * Because of erasure, at compile time the injector can only guarantee that it
 * returns something that extends Communication, not necessarily C. The cast and
 * @SuppressWarnings will help with that.
 */
@SuppressWarnings("unchecked")
public static <C extends Communication> Provider<C> getCommunicationProvider(
    C communication) {
  return (Provider<C>) injector.getProvider(Key.get(communication.getClass(),
      Names.named(communication.toString())));
}

另请注意,由于删除,没有其他方法可以获取 C 类型的类文字,因此使用 Call 的模拟或动态代理将会失败。

如果你想绑定(bind)SomeOtherInterface<Call>而不是Provider<Call> ,您仍然可以这样做,但是您需要使用 Guice 的 Types util class 动态创建 ParameterizedType并将其用作 Key#get(Type, Annotation) 的输入。有关创建 ParameterizedType 的更多背景信息实现,请阅读 this SO answer .

关于java - 使用 Guice 按类型和注释检索单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18968410/

相关文章:

java - 设置嵌套的 TextView 文本

java - 如何验证 Guice 作用域在测试中的使用情况?

java - Guice:在 Binder 内独立使用相同的实例

java - Gradle错误:在IDEA中运行Android APP时

java - IOException 在 http 错误代码返回时在客户端捕获

java - 通过 tcp 套接字从 java 服务器向 Android 客户端返回消息

java - 从 json 响应将字符串转换为 android 中的数组

Java - 注册所有用@MyAnnotation 注释的类

java - 如何使用 Guice 向 bean 注入(inject)简单的配置参数?

java - gwt 使用 guice - 引导或部署时发生的情况