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:
- (recommended) The constructor is explicitly annotated with
@Inject(bothcom.google.inject.Injectandjavax.inject.Injectare supported). - or, the constructor takes zero arguments, and
- the constructor is non-private and defined in a non-private class (Guice supports private constructor only when it is defined in a private class, however, private constructors are not recommended because they can be slow in Guice due to the cost of reflection).
- the injector has not opted in to require explicit @Inject constructor, seeexplicit @Inject constructorssection below.
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:
- The constructor takes one or more arguments and is not annotated with
@Inject. - There are more than one
@Injectannotated constructors. - The constructor is defined in a non-static nested class. Inner classes have an implicit reference to their enclosing class that cannot be injected.
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.