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 import java.lang.annotation.Annotation; 31 import java.lang.reflect.Method; 32 33 /** 34 * A module whose configuration information is hidden from its environment by default. Only bindings 35 * that are explicitly exposed will be available to other modules and to the users of the injector. 36 * This module may expose the bindings it creates and the bindings of the modules it installs. 37 * 38 * <p>A private module can be nested within a regular module or within another private module using 39 * {@link Binder#install install()}. Its bindings live in a new environment that inherits bindings, 40 * type converters, scopes, and interceptors from the surrounding ("parent") environment. When you 41 * nest multiple private modules, the result is a tree of environments where the injector's 42 * environment is the root. 43 * 44 * <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link 45 * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link Exposed} 46 * annotation: 47 * 48 * <pre> 49 * public class FooBarBazModule extends PrivateModule { 50 * protected void configure() { 51 * bind(Foo.class).to(RealFoo.class); 52 * expose(Foo.class); 53 * 54 * install(new TransactionalBarModule()); 55 * expose(Bar.class).annotatedWith(Transactional.class); 56 * 57 * bind(SomeImplementationDetail.class); 58 * install(new MoreImplementationDetailsModule()); 59 * } 60 * 61 * {@literal @}Provides {@literal @}Exposed 62 * public Baz provideBaz() { 63 * return new SuperBaz(); 64 * } 65 * } 66 * </pre> 67 * 68 * <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent 69 * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the 70 * root environment. Such bindings are shared among all environments in the tree. 71 * 72 * <p>The scope of a binding is constrained to its environment. A singleton bound in a private 73 * module will be unique to its environment. But a binding for the same type in a different private 74 * module will yield a different instance. 75 * 76 * <p>A shared binding that injects the {@code Injector} gets the root injector, which only has 77 * access to bindings in the root environment. An explicit binding that injects the {@code Injector} 78 * gets access to all bindings in the child environment. 79 * 80 * <p>To promote a just-in-time binding to an explicit binding, bind it: 81 * 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 94 @Override configure(Binder binder)95 public final synchronized void configure(Binder binder) { 96 checkState(this.binder == null, "Re-entry is not allowed."); 97 98 // Guice treats PrivateModules specially and passes in a PrivateBinder automatically. 99 this.binder = (PrivateBinder) binder.skipSources(PrivateModule.class); 100 try { 101 configure(); 102 } finally { 103 this.binder = null; 104 } 105 } 106 107 /** 108 * Creates bindings and other configurations private to this module. Use {@link #expose(Class) 109 * expose()} to make the bindings in this module available externally. 110 */ configure()111 protected abstract void configure(); 112 113 /** Makes the binding for {@code key} available to other modules and the injector. */ expose(Key<T> key)114 protected final <T> void expose(Key<T> key) { 115 binder().expose(key); 116 } 117 118 /** 119 * Makes a binding for {@code type} available to other modules and the injector. Use {@link 120 * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a 121 * binding annotation. 122 */ expose(Class<?> type)123 protected final AnnotatedElementBuilder expose(Class<?> type) { 124 return binder().expose(type); 125 } 126 127 /** 128 * Makes a binding for {@code type} available to other modules and the injector. Use {@link 129 * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a 130 * binding annotation. 131 */ expose(TypeLiteral<?> type)132 protected final AnnotatedElementBuilder expose(TypeLiteral<?> type) { 133 return binder().expose(type); 134 } 135 136 // everything below is copied from AbstractModule 137 138 /** Returns the current binder. */ binder()139 protected final PrivateBinder binder() { 140 checkState(binder != null, "The binder can only be used inside configure()"); 141 return binder; 142 } 143 144 /** @see Binder#bindScope(Class, Scope) */ bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope)145 protected final void bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) { 146 binder().bindScope(scopeAnnotation, scope); 147 } 148 149 /** @see Binder#bind(Key) */ bind(Key<T> key)150 protected final <T> LinkedBindingBuilder<T> bind(Key<T> key) { 151 return binder().bind(key); 152 } 153 154 /** @see Binder#bind(TypeLiteral) */ bind(TypeLiteral<T> typeLiteral)155 protected final <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) { 156 return binder().bind(typeLiteral); 157 } 158 159 /** @see Binder#bind(Class) */ bind(Class<T> clazz)160 protected final <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) { 161 return binder().bind(clazz); 162 } 163 164 /** @see Binder#bindConstant() */ bindConstant()165 protected final AnnotatedConstantBindingBuilder bindConstant() { 166 return binder().bindConstant(); 167 } 168 169 /** @see Binder#install(Module) */ install(Module module)170 protected final void install(Module module) { 171 binder().install(module); 172 } 173 174 /** @see Binder#addError(String, Object[]) */ addError(String message, Object... arguments)175 protected final void addError(String message, Object... arguments) { 176 binder().addError(message, arguments); 177 } 178 179 /** @see Binder#addError(Throwable) */ addError(Throwable t)180 protected final void addError(Throwable t) { 181 binder().addError(t); 182 } 183 184 /** @see Binder#addError(Message) */ addError(Message message)185 protected final void addError(Message message) { 186 binder().addError(message); 187 } 188 189 /** @see Binder#requestInjection(Object) */ requestInjection(Object instance)190 protected final void requestInjection(Object instance) { 191 binder().requestInjection(instance); 192 } 193 194 /** @see Binder#requestStaticInjection(Class[]) */ requestStaticInjection(Class<?>.... types)195 protected final void requestStaticInjection(Class<?>... types) { 196 binder().requestStaticInjection(types); 197 } 198 199 /*if[AOP]*/ 200 /** 201 * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, 202 * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) 203 */ bindInterceptor( Matcher<? super Class<?>> classMatcher, Matcher<? super Method> methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors)204 protected final void bindInterceptor( 205 Matcher<? super Class<?>> classMatcher, 206 Matcher<? super Method> methodMatcher, 207 org.aopalliance.intercept.MethodInterceptor... interceptors) { 208 binder().bindInterceptor(classMatcher, methodMatcher, interceptors); 209 } 210 /*end[AOP]*/ 211 212 /** Instructs Guice to require a binding to the given key. */ requireBinding(Key<?> key)213 protected final void requireBinding(Key<?> key) { 214 binder().getProvider(key); 215 } 216 217 /** Instructs Guice to require a binding to the given type. */ requireBinding(Class<?> type)218 protected final void requireBinding(Class<?> type) { 219 binder().getProvider(type); 220 } 221 222 /** @see Binder#getProvider(Key) */ getProvider(Key<T> key)223 protected final <T> Provider<T> getProvider(Key<T> key) { 224 return binder().getProvider(key); 225 } 226 227 /** @see Binder#getProvider(Class) */ getProvider(Class<T> type)228 protected final <T> Provider<T> getProvider(Class<T> type) { 229 return binder().getProvider(type); 230 } 231 232 /** 233 * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, 234 * com.google.inject.spi.TypeConverter) 235 */ convertToTypes( Matcher<? super TypeLiteral<?>> typeMatcher, TypeConverter converter)236 protected final void convertToTypes( 237 Matcher<? super TypeLiteral<?>> typeMatcher, TypeConverter converter) { 238 binder().convertToTypes(typeMatcher, converter); 239 } 240 241 /** @see Binder#currentStage() */ currentStage()242 protected final Stage currentStage() { 243 return binder().currentStage(); 244 } 245 246 /** @see Binder#getMembersInjector(Class) */ getMembersInjector(Class<T> type)247 protected <T> MembersInjector<T> getMembersInjector(Class<T> type) { 248 return binder().getMembersInjector(type); 249 } 250 251 /** @see Binder#getMembersInjector(TypeLiteral) */ getMembersInjector(TypeLiteral<T> type)252 protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) { 253 return binder().getMembersInjector(type); 254 } 255 256 /** 257 * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener) 258 */ bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener)259 protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) { 260 binder().bindListener(typeMatcher, listener); 261 } 262 263 /** 264 * @see Binder#bindListener(Matcher, ProvisionListener...) 265 * @since 4.0 266 */ bindListener( Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners)267 protected void bindListener( 268 Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners) { 269 binder().bindListener(bindingMatcher, listeners); 270 } 271 } 272