Guice - MapBinder 的默认绑定

Guice - Default binding for MapBinder

我正在使用 MapBinder 将键映射到它们各自的实现。现在我有这样的东西:

MapBinder<String, Processor> processor
                = MapBinder.newMapBinder(binder(), String.class, Processor.class);
        processor.addBinding("a1").to(a1Processor.class).in(Scopes.SINGLETON);
        processor.addBinding("a2").to(a2Processor.class).in(Scopes.SINGLETON);
        processor.addBinding("a3").to(a3Processor.class).in(Scopes.SINGLETON);

它正在按照预期的方式工作。但现在我正在考虑创建一个 DefaultProcessor 并将除 a2a3 之外的任何 String 绑定到此 DefaultProcessor。可以这样做吗?

来自MapBinderJavadocs

An API to bind multiple map entries separately, only to later inject them as a complete map.

所以您在问题中提出的问题无法通过 MapBinder 实现。

尽管您可以围绕 Map<String, Processor> 编写一个包装器并使用它。

建议:

@Singleton
class StringProcessorWrapper {

    private final Map<String, Processor> processorMap;
    private final Processor defaultProcessor;

    @Inject
    public StringProcessorWrapper(Map<String, Processor> processorMap, @Named("default") Processor defaultProcessor) {
        this.processorMap = processorMap;
        this.defaultProcessor = defaultProcessor;
    }

    public Processor get(String key) {
        return processorMap.getOrDefault(key, defaultProcessor);
    }
}

为此,您必须在 guice 模块的 configure 方法中添加一个绑定,如下所示:

bind(Processor.class).annotatedWith(Names.named("default")).to(DefaultProcessor.class).in(Scopes.SINGLETON);

现在您可以注入 StringProcessor 包装器并使用它。

当你需要在很多地方使用Map时,这个建议很有价值。对于单个 class,您可以只注入默认值并在缺少密钥时使用它。

如果您只想使用地图并避免添加单独的默认绑定,您可以在 MapBinder 中使用 "default" 键和 [=20 的 get 方法添加第四个绑定=] 做这样的事情:

processorMap.getOrDefault(key, processorMap.get("default"));