java - 如何将 Guice AssistedInject 与接口(interface)的多个实现一起使用?

标签 java guice factory assisted-inject

我找不到如何进行“动态辅助注入(inject)”的方法。 我的意思是我想根据参数向工厂提供它需要在运行时使用的实现类名。 这是我目前拥有的:

interface Letter {}

abstract class ALetter implements Letter {
    public ALetter(T1 t1, T2 t2) {...} 
}

class A implements Letter {
    public static final NAME = "A";

    @Inject
    public A(@Assisted T1 t1, T2 t2) { super(t1, t2); }
}

class B implements Letter {
    public static final NAME = "B";

    @Inject
    public B(@Assisted T1 t1, T2 t2) { super(t1, t2); }
}

考虑到我有 T1 但我需要注入(inject) T2,我希望能够根据他们的名字加载 A 或 B。 它可能看起来像:

class MyClass {
    @Inject
    public MyClass(RequestData data, MyConfig config, ILetterFactory letterFactory) {
        Letter letter = letterFactory.get(data.getLetterName(), config.getT2());
    }
}

我会使用类似的东西配置 ILetterFactory:

install(new FactoryModuleBuilder().build(ILetterFactory.class));

但我知道这目前行不通,因为字母名称不是我的构造函数的真实参数,而 Guice 只是不能那样工作。不过,它应该能让您了解我想要什么。

我目前找到的唯一解决方案不使用 Guice:我有自己的工厂,它根据名称解析类构造函数(通过 Map<String, Constructor> ),并调用 newInstance为它提供适当的参数(除了在工厂本身之外根本没有注入(inject))。

有没有办法使用 Guice 来避免自己创建那个工厂? 谢谢

最佳答案

FactoryModuleBuilder 并不像您想象的那么强大——它没有在实现之间切换的规定,并且仅用于将注入(inject)的依赖项与其他构造函数参数混合。幸运的是,Guice 使您的工厂易于编写。听起来您正在寻找的是此接口(interface)的实现:

public interface ILetterFactory {
  /** This assumes that T2 is a Guice-satisfied dependency,
    * and not meant to be @Assisted, so leave it out of the interface. */
  Letter get(String which);
}

选择之一是让 Guice 为您的实例提供 Provider,如果您的 Letters 具有广泛不同的 dep,或者如果您的 dep 列表很长或经常更改,这将是最有用的。如果 A 和 B 需要辅助依赖,替换 Provider<A>A.Factory您已通过 FactoryModuleBuilder 绑定(bind)。

public class LetterFactory implements ILetterFactory {
  @Inject Provider<A> aProvider;
  @Inject Provider<B> bProvider;

  @Override public Letter get(String which) {
    if (A.NAME.equals(which)) {
      return aProvider.get();
    } else if (B.NAME.equals(which)) {
      return bProvider.get();
    } else {
      throw new IllegalArgumentException("Letter does not exist");
    }
  }
}

选择二,您负责从 Guice 创建一个新实例。如果你的 deps 列表发生变化,它需要更多的维护,并且不能很好地使用 AOP 和其他类似的功能,但如果你的 Letters 需要辅助参数和一小组类似的 dep,它可能会少一些工作:

public class LetterFactory implements ILetterFactory {
  @Inject Provider<T2> t2Provider;

  @Override public Letter get(String which) {
    if (A.NAME.equals(which)) {
      return new A(t2Provider.get());
    } else if (B.NAME.equals(which)) {
      return new B(t2Provider.get());
    } else {
      throw new IllegalArgumentException("Letter does not exist");
    }
  }
}

关于java - 如何将 Guice AssistedInject 与接口(interface)的多个实现一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27442352/

相关文章:

java - 如何按字母顺序对 ArrayList 进行排序并将其与 setText 方法一起使用?

java - 如何使用循环从 hashmap 中获取值

java - `ProvisionException` 被缓存并且构造函数代码永远不会重试

Java Guice 提供者

c++ - "factory"方法是正确的模式吗?

java - 匹配 ListView 行的背景颜色 Espresso

java - Xuggler的IPacket如何与FLV标签或标签部分对应?

scala - 注入(inject) scala 对象

C# - 程序员面试挑战 - 接口(interface)和模式编程

php - Laravel 工厂不调用回调 'afterCreating'