Skip to main content

Generating bindings

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

Supplier Generator Module

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

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 a Supplier of that instance. Otherwise, we generate a binding for a Supplier that always supplies null.

Running the example

We need to create a new Injector and install a SupplierGeneratorModule. We also need to bind a String to a "Hello, World" value. To let Injector know that we may be requesting instances of Supplier<String> and Supplier<Integer> we also have to bind 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<Supplier<String>>() {});System.out.println(stringSupplier.get()); // "Hello, World"
Supplier<Integer> integerSupplier = injector.getInstance(new Key<Supplier<Integer>>() {});System.out.println(integerSupplier.get()); // "null"

We then receive instances of Supplier<String> and Supplier<Integer> from the Injector.

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

You can find example sources on GitHub

Generating bindings using @Provides methods

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

Here is how a SupplierGeneratorModule could look like if we defined 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;        }    }}