1 /* 2 * Copyright (C) 2006 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.checkNotNull; 20 import static com.google.common.base.Preconditions.checkState; 21 22 import com.google.inject.binder.AnnotatedBindingBuilder; 23 import com.google.inject.binder.AnnotatedConstantBindingBuilder; 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 support class for {@link Module}s which reduces repetition and results in a more readable 35 * configuration. Simply extend this class, implement {@link #configure()}, and call the inherited 36 * methods which mirror those found in {@link Binder}. For example: 37 * 38 * <pre> 39 * public class MyModule extends AbstractModule { 40 * protected void configure() { 41 * bind(Service.class).to(ServiceImpl.class).in(Singleton.class); 42 * bind(CreditCardPaymentService.class); 43 * bind(PaymentService.class).to(CreditCardPaymentService.class); 44 * bindConstant().annotatedWith(Names.named("port")).to(8080); 45 * } 46 * } 47 * </pre> 48 * 49 * @author crazybob@google.com (Bob Lee) 50 */ 51 public abstract class AbstractModule implements Module { 52 53 Binder binder; 54 55 @Override 56 public final synchronized void configure(Binder builder) { 57 checkState(this.binder == null, "Re-entry is not allowed."); 58 59 this.binder = checkNotNull(builder, "builder"); 60 try { 61 configure(); 62 } finally { 63 this.binder = null; 64 } 65 } 66 67 /** Configures a {@link Binder} via the exposed methods. */ 68 protected void configure() {} 69 70 /** Gets direct access to the underlying {@code Binder}. */ 71 protected Binder binder() { 72 checkState(binder != null, "The binder can only be used inside configure()"); 73 return binder; 74 } 75 76 /** @see Binder#bindScope(Class, Scope) */ 77 protected void bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) { 78 binder().bindScope(scopeAnnotation, scope); 79 } 80 81 /** @see Binder#bind(Key) */ 82 protected <T> LinkedBindingBuilder<T> bind(Key<T> key) { 83 return binder().bind(key); 84 } 85 86 /** @see Binder#bind(TypeLiteral) */ 87 protected <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) { 88 return binder().bind(typeLiteral); 89 } 90 91 /** @see Binder#bind(Class) */ 92 protected <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) { 93 return binder().bind(clazz); 94 } 95 96 /** @see Binder#bindConstant() */ 97 protected AnnotatedConstantBindingBuilder bindConstant() { 98 return binder().bindConstant(); 99 } 100 101 /** @see Binder#install(Module) */ 102 protected void install(Module module) { 103 binder().install(module); 104 } 105 106 /** @see Binder#addError(String, Object[]) */ 107 protected void addError(String message, Object... arguments) { 108 binder().addError(message, arguments); 109 } 110 111 /** @see Binder#addError(Throwable) */ 112 protected void addError(Throwable t) { 113 binder().addError(t); 114 } 115 116 /** 117 * @see Binder#addError(Message) 118 * @since 2.0 119 */ 120 protected void addError(Message message) { 121 binder().addError(message); 122 } 123 124 /** 125 * @see Binder#requestInjection(Object) 126 * @since 2.0 127 */ 128 protected void requestInjection(Object instance) { 129 binder().requestInjection(instance); 130 } 131 132 /** @see Binder#requestStaticInjection(Class[]) */ 133 protected void requestStaticInjection(Class<?>... types) { 134 binder().requestStaticInjection(types); 135 } 136 137 /*if[AOP]*/ 138 /** 139 * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, 140 * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) 141 */ 142 protected void bindInterceptor( 143 Matcher<? super Class<?>> classMatcher, 144 Matcher<? super Method> methodMatcher, 145 org.aopalliance.intercept.MethodInterceptor... interceptors) { 146 binder().bindInterceptor(classMatcher, methodMatcher, interceptors); 147 } 148 /*end[AOP]*/ 149 150 /** 151 * Adds a dependency from this module to {@code key}. When the injector is created, Guice will 152 * report an error if {@code key} cannot be injected. Note that this requirement may be satisfied 153 * by implicit binding, such as a public no-arguments constructor. 154 * 155 * @since 2.0 156 */ 157 protected void requireBinding(Key<?> key) { 158 binder().getProvider(key); 159 } 160 161 /** 162 * Adds a dependency from this module to {@code type}. When the injector is created, Guice will 163 * report an error if {@code type} cannot be injected. Note that this requirement may be satisfied 164 * by implicit binding, such as a public no-arguments constructor. 165 * 166 * @since 2.0 167 */ 168 protected void requireBinding(Class<?> type) { 169 binder().getProvider(type); 170 } 171 172 /** 173 * @see Binder#getProvider(Key) 174 * @since 2.0 175 */ 176 protected <T> Provider<T> getProvider(Key<T> key) { 177 return binder().getProvider(key); 178 } 179 180 /** 181 * @see Binder#getProvider(Class) 182 * @since 2.0 183 */ 184 protected <T> Provider<T> getProvider(Class<T> type) { 185 return binder().getProvider(type); 186 } 187 188 /** 189 * @see Binder#convertToTypes 190 * @since 2.0 191 */ 192 protected void convertToTypes( 193 Matcher<? super TypeLiteral<?>> typeMatcher, TypeConverter converter) { 194 binder().convertToTypes(typeMatcher, converter); 195 } 196 197 /** 198 * @see Binder#currentStage() 199 * @since 2.0 200 */ 201 protected Stage currentStage() { 202 return binder().currentStage(); 203 } 204 205 /** 206 * @see Binder#getMembersInjector(Class) 207 * @since 2.0 208 */ 209 protected <T> MembersInjector<T> getMembersInjector(Class<T> type) { 210 return binder().getMembersInjector(type); 211 } 212 213 /** 214 * @see Binder#getMembersInjector(TypeLiteral) 215 * @since 2.0 216 */ 217 protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) { 218 return binder().getMembersInjector(type); 219 } 220 221 /** 222 * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener) 223 * @since 2.0 224 */ 225 protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) { 226 binder().bindListener(typeMatcher, listener); 227 } 228 229 /** 230 * @see Binder#bindListener(Matcher, ProvisionListener...) 231 * @since 4.0 232 */ 233 protected void bindListener( 234 Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listener) { 235 binder().bindListener(bindingMatcher, listener); 236 } 237 } 238