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<Supplier<String>>() {});System.out.println(stringSupplier.get()); // "Hello, World"
Supplier<Integer> integerSupplier = injector.getInstance(new Key<Supplier<Integer>>() {});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;        }    }}