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 17package com.google.inject; 18 19import static com.google.common.base.Preconditions.checkState; 20 21import com.google.inject.binder.AnnotatedBindingBuilder; 22import com.google.inject.binder.AnnotatedConstantBindingBuilder; 23import com.google.inject.binder.AnnotatedElementBuilder; 24import com.google.inject.binder.LinkedBindingBuilder; 25import com.google.inject.matcher.Matcher; 26import com.google.inject.spi.Message; 27import com.google.inject.spi.ProvisionListener; 28import com.google.inject.spi.TypeConverter; 29import com.google.inject.spi.TypeListener; 30 31import java.lang.annotation.Annotation; 32import 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 */ 89public 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