Skip to main content

Generating bindings

In this tutorial we will generate a binding for an arbitrary type Supplier.

Supplier Generator Module

We define a standalone module responsible solely for defining the Supplier<T> generator.

public static final class SupplierGeneratorModule extends AbstractModule {

@Override
protected void configure() {
generate(Supplier.class, (bindings, scope, key) -> {
Binding<?> binding = bindings.get(key.getTypeParameter(0));
return binding != null ?
binding.mapInstance(instance -> () -> instance) :
Binding.toInstance(() -> null);
});
}
}

If there is a known binding for type T, as in Supplier<T>, we generate a binding for that instance's Supplier. Otherwise, we generate a binding for a Supplier that always supplies null.

Running the example

We need to create a new Injector and install the SupplierGeneratorModule. We also need to bind a String to a "Hello, World" value. To let the Injector know that we may be requesting instances of Supplier<String> and Supplier<Integer>, we also need to bind the corresponding keys.

Injector injector = Injector.of(ModuleBuilder.create()
.install(new SupplierGeneratorModule())
.bind(String.class).toInstance("Hello, World")
.bind(new Key<Supplier<String>>() {})
.bind(new Key<Supplier<Integer>>() {})
.build());
Supplier<String> stringSupplier = injector.getInstance(new Key<>() {});
System.out.println(stringSupplier.get()); // "Hello, World"

Supplier<Integer> integerSupplier = injector.getInstance(new Key<>() {});
System.out.println(integerSupplier.get()); // "null"

Then we receive instances of Supplier<String> and Supplier<Integer> from the Injector.

  • When we call stringSupplier.get() we receive a "Hello, World" string, because the binding for String was manually provided.
  • When we call integerSupplier.get() we receive a null, because the binding for Integer was never provided.

You can find example sources on GitHub

Generating bindings using @Provides methods

In the example above, we defined a binding generator in SupplierGeneratorModule using the AbstractModule#generate method inside the configure method. Alternatively, you can define binding generators using methods annotated with @Provides annotation. We will use a special OptionalDependency class as a dependency, which lets us know if there is a provided binding for some type.

This is what a SupplierGeneratorModule might look like if we define a Supplier binding generator using @Provides annotation:

public static final class SupplierGeneratorModule extends AbstractModule {
@Provides
<T> Supplier<T> supplier(OptionalDependency<T> optionalDependency) {
if (optionalDependency.isPresent()) {
return optionalDependency::get;
} else {
return () -> null;
}
}
}