Home | History | Annotate | Download | only in inject
      1 /**
      2  * Copyright (C) 2008 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.inject;
     18 
     19 import static com.google.common.base.Preconditions.checkState;
     20 
     21 import com.google.inject.binder.AnnotatedBindingBuilder;
     22 import com.google.inject.binder.AnnotatedConstantBindingBuilder;
     23 import com.google.inject.binder.AnnotatedElementBuilder;
     24 import com.google.inject.binder.LinkedBindingBuilder;
     25 import com.google.inject.matcher.Matcher;
     26 import com.google.inject.spi.Message;
     27 import com.google.inject.spi.ProvisionListener;
     28 import com.google.inject.spi.TypeConverter;
     29 import com.google.inject.spi.TypeListener;
     30 
     31 import java.lang.annotation.Annotation;
     32 import java.lang.reflect.Method;
     33 
     34 /**
     35  * A module whose configuration information is hidden from its environment by default. Only bindings
     36  * that are explicitly exposed will be available to other modules and to the users of the injector.
     37  * This module may expose the bindings it creates and the bindings of the modules it installs.
     38  *
     39  * <p>A private module can be nested within a regular module or within another private module using
     40  * {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
     41  * type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
     42  * nest multiple private modules, the result is a tree of environments where the injector's
     43  * environment is the root.
     44  *
     45  * <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
     46  * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
     47  * Exposed} annotation:
     48  *
     49  * <pre>
     50  * public class FooBarBazModule extends PrivateModule {
     51  *   protected void configure() {
     52  *     bind(Foo.class).to(RealFoo.class);
     53  *     expose(Foo.class);
     54  *
     55  *     install(new TransactionalBarModule());
     56  *     expose(Bar.class).annotatedWith(Transactional.class);
     57  *
     58  *     bind(SomeImplementationDetail.class);
     59  *     install(new MoreImplementationDetailsModule());
     60  *   }
     61  *
     62  *   {@literal @}Provides {@literal @}Exposed
     63  *   public Baz provideBaz() {
     64  *     return new SuperBaz();
     65  *   }
     66  * }
     67  * </pre>
     68  *
     69  * <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
     70  * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
     71  * root environment. Such bindings are shared among all environments in the tree.
     72  *
     73  * <p>The scope of a binding is constrained to its environment. A singleton bound in a private
     74  * module will be unique to its environment. But a binding for the same type in a different private
     75  * module will yield a different instance.
     76  *
     77  * <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
     78  * access to bindings in the root environment. An explicit binding that injects the {@code Injector}
     79  * gets access to all bindings in the child environment.
     80  *
     81  * <p>To promote a just-in-time binding to an explicit binding, bind it:
     82  * <pre>
     83  *   bind(FooImpl.class);
     84  * </pre>
     85  *
     86  * @author jessewilson (at) google.com (Jesse Wilson)
     87  * @since 2.0
     88  */
     89 public abstract class PrivateModule implements Module {
     90 
     91   /** Like abstract module, the binder of the current private module */
     92   private PrivateBinder binder;
     93 
     94   public final synchronized void configure(Binder binder) {
     95     checkState(this.binder == null, "Re-entry is not allowed.");
     96 
     97     // Guice treats PrivateModules specially and passes in a PrivateBinder automatically.
     98     this.binder = (PrivateBinder) binder.skipSources(PrivateModule.class);
     99     try {
    100       configure();
    101     } finally {
    102       this.binder = null;
    103     }
    104   }
    105 
    106   /**
    107    * Creates bindings and other configurations private to this module. Use {@link #expose(Class)
    108    * expose()} to make the bindings in this module available externally.
    109    */
    110   protected abstract void configure();
    111 
    112   /** Makes the binding for {@code key} available to other modules and the injector. */
    113   protected final <T> void expose(Key<T> key) {
    114     binder().expose(key);
    115   }
    116 
    117   /**
    118    * Makes a binding for {@code type} available to other modules and the injector. Use {@link
    119    * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
    120    * binding annotation.
    121    */
    122   protected final AnnotatedElementBuilder expose(Class<?> type) {
    123     return binder().expose(type);
    124   }
    125 
    126   /**
    127    * Makes a binding for {@code type} available to other modules and the injector. Use {@link
    128    * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
    129    * binding annotation.
    130    */
    131   protected final AnnotatedElementBuilder expose(TypeLiteral<?> type) {
    132     return binder().expose(type);
    133   }
    134 
    135   // everything below is copied from AbstractModule
    136 
    137   /**
    138    * Returns the current binder.
    139    */
    140   protected final PrivateBinder binder() {
    141     checkState(binder != null, "The binder can only be used inside configure()");
    142     return binder;
    143   }
    144 
    145   /**
    146    * @see Binder#bindScope(Class, Scope)
    147    */
    148   protected final void bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) {
    149     binder().bindScope(scopeAnnotation, scope);
    150   }
    151 
    152   /**
    153    * @see Binder#bind(Key)
    154    */
    155   protected final <T> LinkedBindingBuilder<T> bind(Key<T> key) {
    156     return binder().bind(key);
    157   }
    158 
    159   /**
    160    * @see Binder#bind(TypeLiteral)
    161    */
    162   protected final <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
    163     return binder().bind(typeLiteral);
    164   }
    165 
    166   /**
    167    * @see Binder#bind(Class)
    168    */
    169   protected final <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
    170     return binder().bind(clazz);
    171   }
    172 
    173   /**
    174    * @see Binder#bindConstant()
    175    */
    176   protected final AnnotatedConstantBindingBuilder bindConstant() {
    177     return binder().bindConstant();
    178   }
    179 
    180   /**
    181    * @see Binder#install(Module)
    182    */
    183   protected final void install(Module module) {
    184     binder().install(module);
    185   }
    186 
    187   /**
    188    * @see Binder#addError(String, Object[])
    189    */
    190   protected final void addError(String message, Object... arguments) {
    191     binder().addError(message, arguments);
    192   }
    193 
    194   /**
    195    * @see Binder#addError(Throwable)
    196    */
    197   protected final void addError(Throwable t) {
    198     binder().addError(t);
    199   }
    200 
    201   /**
    202    * @see Binder#addError(Message)
    203    */
    204   protected final void addError(Message message) {
    205     binder().addError(message);
    206   }
    207 
    208   /**
    209    * @see Binder#requestInjection(Object)
    210    */
    211   protected final void requestInjection(Object instance) {
    212     binder().requestInjection(instance);
    213   }
    214 
    215   /**
    216    * @see Binder#requestStaticInjection(Class[])
    217    */
    218   protected final void requestStaticInjection(Class<?>... types) {
    219     binder().requestStaticInjection(types);
    220   }
    221 
    222   /*if[AOP]*/
    223   /**
    224    * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
    225    */
    226   protected final void bindInterceptor(Matcher<? super Class<?>> classMatcher,
    227       Matcher<? super Method> methodMatcher,
    228       org.aopalliance.intercept.MethodInterceptor... interceptors) {
    229     binder().bindInterceptor(classMatcher, methodMatcher, interceptors);
    230   }
    231   /*end[AOP]*/
    232 
    233   /**
    234    * Instructs Guice to require a binding to the given key.
    235    */
    236   protected final void requireBinding(Key<?> key) {
    237     binder().getProvider(key);
    238   }
    239 
    240   /**
    241    * Instructs Guice to require a binding to the given type.
    242    */
    243   protected final void requireBinding(Class<?> type) {
    244     binder().getProvider(type);
    245   }
    246 
    247   /**
    248    * @see Binder#getProvider(Key)
    249    */
    250   protected final <T> Provider<T> getProvider(Key<T> key) {
    251     return binder().getProvider(key);
    252   }
    253 
    254   /**
    255    * @see Binder#getProvider(Class)
    256    */
    257   protected final <T> Provider<T> getProvider(Class<T> type) {
    258     return binder().getProvider(type);
    259   }
    260 
    261   /**
    262    * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)
    263    */
    264   protected final void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
    265       TypeConverter converter) {
    266     binder().convertToTypes(typeMatcher, converter);
    267   }
    268 
    269   /**
    270    * @see Binder#currentStage()
    271    */
    272   protected final Stage currentStage() {
    273     return binder().currentStage();
    274   }
    275 
    276   /**
    277    * @see Binder#getMembersInjector(Class)
    278    */
    279   protected <T> MembersInjector<T> getMembersInjector(Class<T> type) {
    280     return binder().getMembersInjector(type);
    281   }
    282 
    283   /**
    284    * @see Binder#getMembersInjector(TypeLiteral)
    285    */
    286   protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) {
    287     return binder().getMembersInjector(type);
    288   }
    289 
    290   /**
    291    * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)
    292    */
    293   protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher,
    294       TypeListener listener) {
    295     binder().bindListener(typeMatcher, listener);
    296   }
    297 
    298   /**
    299    * @see Binder#bindListener(Matcher, ProvisionListener...)
    300    * @since 4.0
    301    */
    302   protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
    303       ProvisionListener... listeners) {
    304     binder().bindListener(bindingMatcher, listeners);
    305   }
    306 }
    307