Extension for binding multiple instances in a collection with Set, Map, and Optional binding capabilities.
—
Map binding functionality that allows multiple modules to contribute key-value entries to a single Map collection. Entries are bound individually and then injected as a complete Map, enabling registry-style patterns where different modules can register services, configurations, or handlers by name.
Creates new MapBinder instances for different key/value type and annotation combinations.
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with no binding annotation.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType);
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with no binding annotation.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType);
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with annotation.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType, Annotation annotation);
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with annotation.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Annotation annotation);
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with annotationType.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, Class<K> keyType, Class<V> valueType, Class<? extends Annotation> annotationType);
/**
* Returns a new mapbinder that collects entries of keyType/valueType in a Map
* that is itself bound with annotationType.
*/
public static <K, V> MapBinder<K, V> newMapBinder(Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Class<? extends Annotation> annotationType);Add key-value entries to the Map collection.
/**
* Returns a binding builder used to add a new entry in the map. Each key must be
* distinct (and non-null). Bound providers will be evaluated each time the map is injected.
*
* It is an error to call this method without also calling one of the to methods on the
* returned binding builder. Scoping elements independently is supported.
*/
public LinkedBindingBuilder<V> addBinding(K key);Configure how duplicate keys are handled.
/**
* Configures the MapBinder to handle duplicate entries.
*
* When multiple equal keys are bound, the value that gets included in the map is arbitrary.
* In addition to the Map<K, V> and Map<K, Provider<V>> maps that are normally bound,
* a Map<K, Set<V>> and Map<K, Set<Provider<V>>> are also bound, which contain all values
* bound to each key.
*
* When multiple modules contribute elements to the map, this configuration option impacts all of them.
*/
public MapBinder<K, V> permitDuplicates();Contribute entries using provider methods with map-specific annotations.
/**
* Annotates methods of a Module to add items to a MapBinder. The method's return
* type, binding annotation and additional key annotation determines what Map this will contribute to.
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface ProvidesIntoMap {}
/**
* Meta-annotation for creating custom map key annotations. When unwrapValue is true,
* the value() type will be the key type for injected map and the value() instances
* will be the keys values.
*/
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
public @interface MapKey {
boolean unwrapValue() default true;
}
/**
* Built-in map key annotation for String keys.
*/
@MapKey(unwrapValue = true)
@Target(METHOD)
@Retention(RUNTIME)
public @interface StringMapKey {
String value();
}
/**
* Built-in map key annotation for Class keys.
*/
@MapKey(unwrapValue = true)
@Target(METHOD)
@Retention(RUNTIME)
public @interface ClassMapKey {
Class<?> value();
}Usage Examples:
Basic Map Binding:
public class SnacksModule extends AbstractModule {
@Override
protected void configure() {
MapBinder<String, Snack> mapbinder =
MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("twix").toInstance(new Twix());
mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
mapbinder.addBinding("skittles").to(Skittles.class);
}
}
// Injection
@Inject
public SnackMachine(Map<String, Snack> snacks) {
this.snacks = snacks; // Contains {"twix" -> Twix, "snickers" -> Snickers, "skittles" -> Skittles}
}Provider Map Injection:
// Can inject Map<K, Provider<V>> for lazy value evaluation
@Inject
public SnackMachine(Map<String, Provider<Snack>> snackProviders) {
this.snackProviders = snackProviders;
// Values are created only when Provider.get() is called
}Annotated Map Binding:
public class HandlersModule extends AbstractModule {
@Override
protected void configure() {
MapBinder<String, RequestHandler> mapbinder = MapBinder.newMapBinder(
binder(), String.class, RequestHandler.class, Names.named("web"));
mapbinder.addBinding("users").to(UserRequestHandler.class);
mapbinder.addBinding("orders").to(OrderRequestHandler.class);
}
}
// Injection
@Inject
public WebServer(@Named("web") Map<String, RequestHandler> handlers) {
this.handlers = handlers;
}Provider Method Binding with String Keys:
public class PluginsModule extends AbstractModule {
@ProvidesIntoMap
@StringMapKey("user")
Plugin provideUserPlugin(UserService userService) {
return new UserPlugin(userService);
}
@ProvidesIntoMap
@StringMapKey("order")
Plugin provideOrderPlugin() {
return new OrderPlugin();
}
@ProvidesIntoMap
@StringMapKey("notification")
@Named("web") // Can combine with binding annotations
Plugin provideWebNotificationPlugin() {
return new WebNotificationPlugin();
}
}Provider Method Binding with Class Keys:
public class ProcessorsModule extends AbstractModule {
@ProvidesIntoMap
@ClassMapKey(String.class)
Processor provideStringProcessor() {
return new StringProcessor();
}
@ProvidesIntoMap
@ClassMapKey(Integer.class)
Processor provideIntegerProcessor() {
return new IntegerProcessor();
}
}
// Injection
@Inject
public ProcessorRegistry(Map<Class<?>, Processor> processors) {
this.processors = processors; // {String.class -> StringProcessor, Integer.class -> IntegerProcessor}
}Custom Map Key Annotation:
// Define custom enum key annotation
public enum Environment { DEV, TEST, PROD }
@MapKey(unwrapValue = true)
@Retention(RUNTIME)
public @interface EnvironmentKey {
Environment value();
}
// Use in provider method
@ProvidesIntoMap
@EnvironmentKey(Environment.PROD)
DatabaseConfig provideProdConfig() {
return new ProductionDatabaseConfig();
}Multiple Modules Contributing:
// CandyModule
public class CandyModule extends AbstractModule {
@Override
protected void configure() {
MapBinder<String, Snack> mapbinder =
MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("chocolate").to(Chocolate.class);
mapbinder.addBinding("gummies").to(Gummies.class);
}
}
// ChipsModule
public class ChipsModule extends AbstractModule {
@Override
protected void configure() {
MapBinder<String, Snack> mapbinder =
MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("doritos").to(Doritos.class);
mapbinder.addBinding("cheetos").to(Cheetos.class);
}
}
// Final injected Map contains entries from both modulesDuplicate Key Handling:
public class ConfigModule extends AbstractModule {
@Override
protected void configure() {
MapBinder<String, String> mapbinder = MapBinder.newMapBinder(binder(), String.class, String.class)
.permitDuplicates(); // Enable duplicate key support
mapbinder.addBinding("env").toInstance("dev");
mapbinder.addBinding("env").toInstance("test"); // Would normally fail without permitDuplicates()
}
}
// With permitDuplicates(), additional Map types are bound:
@Inject Map<String, Set<String>> multiValueMap; // {"env" -> {"dev", "test"}}
@Inject Map<String, Set<Provider<String>>> multiProviderMap;Map<K, Provider<V>> for lazy value evaluationMap<K, Set<V>> bindingsInstall with Tessl CLI
npx tessl i tessl/maven-com-google-inject-extensions--guice-multibindings