guice-“动态”绑定?

cbjzeqam  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(408)

请考虑以下代码段:

// some class, somewhere - CANNOT MODIFY IT
public class SystemOutPrinter implements Printer {

  private final String prefix;
  private final String suffix;

  @Inject
  public Printer(
      @Named("prefix") String prefix,
      @Named("suffix") String suffix) {
    this.prefix = prefix;
    this.suffix = suffix;
  }

  @Override
  public void print(String line) {
    System.out.println(prefix + line + suffix);
  }
}

...

// my "regular" binding, in some module
bind(Key.get(String.class, Names.named("prefix"))).toInstance("> ");
...

// runtime-provided values:
Class<? extends Printer> printerClass = SystemOutPrinter.class;
Key<String> suffixKey = Key.get(String.class, Names.named("suffix"));

// my "dynamic" binding, probably in runtime
Printer shouter = instantiate(printerClass, suffixKey, "!");
Printer asker = instantiate(printerClass, suffixKey, "?");

...

// the example usage of the above guice-injected Printers
shouter.print("test");
asker.print("test");

// the expected output:
// > test!
// > test?

如您所见,我需要注入一个全局“前缀”(很简单)和一个每个示例的“后缀”。通常在这种情况下,我会将@assistedinject与factory.create(字符串后缀)方法一起使用-但在这种情况下,我不能,因为systemoutprinter类不能修改。请假设我甚至不知道它的来源。我只得到一个引用(运行时!)到printerclass和后缀键及其值(“!”或“?”)。在运行时,我甚至不知道“suffix”的绑定注解是什么样子。我需要做的就是实现这个方法:

public static <T> T instantiate(Class<? extends T> cls, Key<String> key, String value) {
  ...?
}

这可以通过在instantiate()方法中构造每个示例的childinjector来实现(请假设我在那里有一个injector示例),但显然这是一个非常昂贵的操作(对于我的injector来说,最长可达毫秒),我负担不起。我希望使用自定义作用域可以实现,但无法让它们工作。
有什么想法吗?

tag5nh1u

tag5nh1u1#

为什么不自己写工厂呢?

public class SystemOutPrinterFactory {
  private final String prefix;

  public SystemOutPrinterFactory(@Named("prefix") String prefix) {
    this.prefix = prefix;
  }

  public SystemOutPrinter createWithSuffix(String suffix) {
    return new SystemOutPrinter(prefix, suffix);
  }
}

这个 SystemOutPrinter 类是公共的,非抽象的,带有公共构造函数,所以这应该可以工作。唯一的缺点是工厂需要知道具体的实现。
如果您不知道实现类,那么您将需要一个子注入器,但是假设这些类是线程安全的,您可以使用memoization来避免创建子注入器两次以上。

相关问题