Guice - "dynamic" 绑定?
Guice - "dynamic" binding?
请考虑以下代码片段:
// 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?
如您所见,我需要注入全局 "prefix"(这很容易)和每个实例 "suffix"。通常在这种情况下,我会使用带有 Factory.create(String suffix) 方法的 @AssistedInject - 但在这种情况下,我不能,因为无法修改 SystemOutPrinter class。请假设我什至不知道它的来源。我得到的只是对 printerClass 和 suffixKey 及其值(“!”或“?”)的引用(运行时!)。在运行时,我什至不知道 "suffix" 的绑定注解是什么样子的。我恰恰需要做的是实现方法:
public static <T> T instantiate(Class<? extends T> cls, Key<String> key, String value) {
...?
}
这可以通过在 instantiate() 方法中构造一个每个实例的 childInjector 来实现(请假设我在那里有 Injector 实例),但显然这是一个非常昂贵的操作(对于我的注入器来说高达 MILLISECONDS)并且我买不起。我希望它可以使用自定义范围实现,但无法让它们工作。
有什么想法吗?
为什么不写自己的工厂?
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
class 是 public 并且具有 public 构造函数的非抽象,所以这应该可以工作。唯一不足的是工厂需要知道具体的实现。
如果您不知道实现 class,那么您将需要一个子注入器,但假设这些 class 是线程安全的,您可以使用 memoization 来避免创建子注射器超过两次。
请考虑以下代码片段:
// 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?
如您所见,我需要注入全局 "prefix"(这很容易)和每个实例 "suffix"。通常在这种情况下,我会使用带有 Factory.create(String suffix) 方法的 @AssistedInject - 但在这种情况下,我不能,因为无法修改 SystemOutPrinter class。请假设我什至不知道它的来源。我得到的只是对 printerClass 和 suffixKey 及其值(“!”或“?”)的引用(运行时!)。在运行时,我什至不知道 "suffix" 的绑定注解是什么样子的。我恰恰需要做的是实现方法:
public static <T> T instantiate(Class<? extends T> cls, Key<String> key, String value) {
...?
}
这可以通过在 instantiate() 方法中构造一个每个实例的 childInjector 来实现(请假设我在那里有 Injector 实例),但显然这是一个非常昂贵的操作(对于我的注入器来说高达 MILLISECONDS)并且我买不起。我希望它可以使用自定义范围实现,但无法让它们工作。
有什么想法吗?
为什么不写自己的工厂?
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
class 是 public 并且具有 public 构造函数的非抽象,所以这应该可以工作。唯一不足的是工厂需要知道具体的实现。
如果您不知道实现 class,那么您将需要一个子注入器,但假设这些 class 是线程安全的,您可以使用 memoization 来避免创建子注射器超过两次。