JustInTimeBindings (original) (raw)

Just-in-time Bindings

Bindings that are created automatically by Guice

When the injector needs an instance of a type, it needs a binding. The bindings in modules are called explicit bindings, and the injector uses them whenever they're available. If a type is needed but there isn't an explicit binding, the injector will attempt to create a Just-In-Time binding. These are also known as JIT bindings or implicit bindings.

@Inject Constructors

Guice can create bindings for concrete types by using the type's injectable constructor. Guice considers a constructor injectable if:

Injectable constructor examples:

public final class Foo { // An @Inject annotated constructor. @Inject Foo(Bar bar) { ... } }

public final class Bar { // A no-arg non private constructor. Bar() {}

private static class Baz { // A private constructor to a private class is also usable by Guice, but // this is not recommended since it can be slow. private Baz() {} } }

A constructor is not injectable if:

Non-injectable constructor examples:

public final class Foo { // Not injectable because the construct takes an argument and there is no // @Inject annotation. Foo(Bar bar) { ... } }

public final class Bar { // Not injectable because the constructor is private private Bar() {}

class Baz { // Not injectable because Baz is not a static inner class Baz() {} } }

Explicit @Inject constructors feature

An application can opt-in to enforce that Guice only use @Inject annotated constructors by calling binder().requireAtInjectOnConstructors() in a module that is installed in the injector. When opted-in, Guice will only consider@Inject annotated constructors and if there is none then aMISSING_CONSTRUCTOR is reported.

TIP: Install Modules.requireAtInjectOnConstructorsModule() to opt-in for@Inject on constructor requirement.

@ImplementedBy

Annotate types tell the injector what their default implementation type is. The@ImplementedBy annotation acts like a linked binding, specifying the subtype to use when building a type.

@ImplementedBy(PayPalCreditCardProcessor.class) public interface CreditCardProcessor { ChargeResult charge(String amount, CreditCard creditCard) throws UnreachableException; }

The above annotation is equivalent to the following bind() statement:

bind(CreditCardProcessor.class).to(PayPalCreditCardProcessor.class);

If a type is in both a bind() statement (as the first argument) and has the@ImplementedBy annotation, the bind() statement is used. The annotation suggests a default implementation that can be overridden with a binding. Use@ImplementedBy carefully; it adds a compile-time dependency from the interface to its implementation.

@ProvidedBy

@ProvidedBy tells the injector about a Provider class that produces instances:

@ProvidedBy(DatabaseTransactionLogProvider.class) public interface TransactionLog { void logConnectException(UnreachableException e); void logChargeResult(ChargeResult result); }

The annotation is equivalent to a toProvider() binding:

bind(TransactionLog.class)
    .toProvider(DatabaseTransactionLogProvider.class);

Like @ImplementedBy, if the type is annotated and used in a bind()statement, the bind() statement will be used.

Enforce Explicit Bindings

New in Guice 3.0

To disable implicit bindings, you can use the requireExplicitBindings API:

final class ExplicitBindingModule extends AbstractModule { @Override protected void configure() { binder().requireExplicitBindings(); } }

Installing the above module will cause Guice to enforce that all bindings must be listed in a Module in order to be injected.