• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
configure(Binder binder)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    */
configure()110   protected abstract void configure();
111 
112   /** Makes the binding for {@code key} available to other modules and the injector. */
expose(Key<T> key)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    */
expose(Class<?> type)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    */
expose(TypeLiteral<?> type)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    */
binder()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    */
bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope)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    */
bind(Key<T> key)155   protected final <T> LinkedBindingBuilder<T> bind(Key<T> key) {
156     return binder().bind(key);
157   }
158 
159   /**
160    * @see Binder#bind(TypeLiteral)
161    */
bind(TypeLiteral<T> typeLiteral)162   protected final <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
163     return binder().bind(typeLiteral);
164   }
165 
166   /**
167    * @see Binder#bind(Class)
168    */
bind(Class<T> clazz)169   protected final <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
170     return binder().bind(clazz);
171   }
172 
173   /**
174    * @see Binder#bindConstant()
175    */
bindConstant()176   protected final AnnotatedConstantBindingBuilder bindConstant() {
177     return binder().bindConstant();
178   }
179 
180   /**
181    * @see Binder#install(Module)
182    */
install(Module module)183   protected final void install(Module module) {
184     binder().install(module);
185   }
186 
187   /**
188    * @see Binder#addError(String, Object[])
189    */
addError(String message, Object... arguments)190   protected final void addError(String message, Object... arguments) {
191     binder().addError(message, arguments);
192   }
193 
194   /**
195    * @see Binder#addError(Throwable)
196    */
addError(Throwable t)197   protected final void addError(Throwable t) {
198     binder().addError(t);
199   }
200 
201   /**
202    * @see Binder#addError(Message)
203    */
addError(Message message)204   protected final void addError(Message message) {
205     binder().addError(message);
206   }
207 
208   /**
209    * @see Binder#requestInjection(Object)
210    */
requestInjection(Object instance)211   protected final void requestInjection(Object instance) {
212     binder().requestInjection(instance);
213   }
214 
215   /**
216    * @see Binder#requestStaticInjection(Class[])
217    */
requestStaticInjection(Class<?>.... types)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    */
bindInterceptor(Matcher<? super Class<?>> classMatcher, Matcher<? super Method> methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors)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    */
requireBinding(Key<?> key)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    */
requireBinding(Class<?> type)243   protected final void requireBinding(Class<?> type) {
244     binder().getProvider(type);
245   }
246 
247   /**
248    * @see Binder#getProvider(Key)
249    */
getProvider(Key<T> key)250   protected final <T> Provider<T> getProvider(Key<T> key) {
251     return binder().getProvider(key);
252   }
253 
254   /**
255    * @see Binder#getProvider(Class)
256    */
getProvider(Class<T> type)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    */
convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher, TypeConverter converter)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    */
currentStage()272   protected final Stage currentStage() {
273     return binder().currentStage();
274   }
275 
276   /**
277    * @see Binder#getMembersInjector(Class)
278    */
getMembersInjector(Class<T> type)279   protected <T> MembersInjector<T> getMembersInjector(Class<T> type) {
280     return binder().getMembersInjector(type);
281   }
282 
283   /**
284    * @see Binder#getMembersInjector(TypeLiteral)
285    */
getMembersInjector(TypeLiteral<T> type)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    */
bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener)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    */
bindListener(Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners)302   protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
303       ProvisionListener... listeners) {
304     binder().bindListener(bindingMatcher, listeners);
305   }
306 }
307