2015-01-15 102 views
1

请考虑下面的代码片段:Guice - “动态”绑定?

// 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? 

正如你看到的,我需要注入全球“前缀”(很容易),并在每实例“后缀”。通常在这种情况下,我会使用带有Factory.create(String suffix)方法的@AssistedInject - 但在这种情况下,我不能,因为SystemOutPrinter类不能被修改。请假设我甚至不知道它的来源。我所得到的只是一个对printerClass和一个suffixKey及其值(“!”或“?”)的引用(runtime!)。在运行时,我甚至不知道“后缀”的绑定注释是怎么样的。我恰恰需要做的就是实现的方法:

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

这是通过构建实例化()方法中每个实例childInjector实现(请假设我有没有进样器实例),但显然这是一个非常昂贵的操作(高达MILLISECONDS,对于我的注射器),我负担不起。我希望使用自定义范围可以实现,但无法让它们工作。

任何想法?

回答

0

为什么不写自己的工厂?

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来避免创建子注入器超过两次。