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 forString
was manually provided. - When calling
integerSupplier.get()
we receive anull
as a binding forInteger
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; } }}