1 /** 2 * Copyright (C) 2009 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.assistedinject; 18 19 import com.google.inject.AbstractModule; 20 import com.google.inject.Key; 21 import com.google.inject.Module; 22 import com.google.inject.Provider; 23 import com.google.inject.TypeLiteral; 24 25 import java.lang.annotation.Annotation; 26 27 /** 28 * Provides a factory that combines the caller's arguments with injector-supplied values to 29 * construct objects. 30 * 31 * <h3>Defining a factory</h3> 32 * Create an interface whose methods return the constructed type, or any of its supertypes. The 33 * method's parameters are the arguments required to build the constructed type. 34 * 35 * <pre>public interface PaymentFactory { 36 * Payment create(Date startDate, Money amount); 37 * }</pre> 38 * 39 * You can name your factory methods whatever you like, such as <i>create</i>, <i>createPayment</i> 40 * or <i>newPayment</i>. 41 * 42 * <h3>Creating a type that accepts factory parameters</h3> 43 * {@code constructedType} is a concrete class with an {@literal @}{@link com.google.inject.Inject 44 * Inject}-annotated constructor. In addition to injector-supplied parameters, the constructor 45 * should have parameters that match each of the factory method's parameters. Each factory-supplied 46 * parameter requires an {@literal @}{@link Assisted} annotation. This serves to document that the 47 * parameter is not bound by your application's modules. 48 * 49 * <pre>public class RealPayment implements Payment { 50 * {@literal @}Inject 51 * public RealPayment( 52 * CreditService creditService, 53 * AuthService authService, 54 * <strong>{@literal @}Assisted Date startDate</strong>, 55 * <strong>{@literal @}Assisted Money amount</strong>) { 56 * ... 57 * } 58 * }</pre> 59 * 60 * <h3>Multiple factory methods for the same type</h3> 61 * If the factory contains many methods that return the same type, you can create multiple 62 * constructors in your concrete class, each constructor marked with with 63 * {@literal @}{@link AssistedInject}, in order to match the different parameters types of the 64 * factory methods. 65 * 66 * <pre>public interface PaymentFactory { 67 * Payment create(Date startDate, Money amount); 68 * Payment createWithoutDate(Money amount); 69 * } 70 * 71 * public class RealPayment implements Payment { 72 * {@literal @}AssistedInject 73 * public RealPayment( 74 * CreditService creditService, 75 * AuthService authService, 76 * <strong>{@literal @}Assisted Date startDate</strong>, 77 * <strong>{@literal @}Assisted Money amount</strong>) { 78 * ... 79 * } 80 * 81 * {@literal @}AssistedInject 82 * public RealPayment( 83 * CreditService creditService, 84 * AuthService authService, 85 * <strong>{@literal @}Assisted Money amount</strong>) { 86 * ... 87 * } 88 * }</pre> 89 * 90 * <h3>Configuring simple factories</h3> 91 * In your {@link Module module}, install a {@code FactoryModuleBuilder} that creates the 92 * factory: 93 * 94 * <pre>install(new FactoryModuleBuilder() 95 * .implement(Payment.class, RealPayment.class) 96 * .build(PaymentFactory.class));</pre> 97 * 98 * As a side-effect of this binding, Guice will inject the factory to initialize it for use. The 99 * factory cannot be used until the injector has been initialized. 100 * 101 * <h3>Configuring complex factories</h3> 102 * Factories can create an arbitrary number of objects, one per each method. Each factory 103 * method can be configured using <code>.implement</code>. 104 * 105 * <pre>public interface OrderFactory { 106 * Payment create(Date startDate, Money amount); 107 * Shipment create(Customer customer, Item item); 108 * Receipt create(Payment payment, Shipment shipment); 109 * } 110 * 111 * [...] 112 * 113 * install(new FactoryModuleBuilder() 114 * .implement(Payment.class, RealPayment.class) 115 * // excluding .implement for Shipment means the implementation class 116 * // will be 'Shipment' itself, which is legal if it's not an interface. 117 * .implement(Receipt.class, RealReceipt.class) 118 * .build(OrderFactory.class));</pre> 119 * </pre> 120 * 121 * <h3>Using the factory</h3> 122 * Inject your factory into your application classes. When you use the factory, your arguments 123 * will be combined with values from the injector to construct an instance. 124 * 125 * <pre>public class PaymentAction { 126 * {@literal @}Inject private PaymentFactory paymentFactory; 127 * 128 * public void doPayment(Money amount) { 129 * Payment payment = paymentFactory.create(new Date(), amount); 130 * payment.apply(); 131 * } 132 * }</pre> 133 * 134 * <h3>Making parameter types distinct</h3> 135 * The types of the factory method's parameters must be distinct. To use multiple parameters of 136 * the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the 137 * parameters. The names must be applied to the factory method's parameters: 138 * 139 * <pre>public interface PaymentFactory { 140 * Payment create( 141 * <strong>{@literal @}Assisted("startDate")</strong> Date startDate, 142 * <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate, 143 * Money amount); 144 * } </pre> 145 * 146 * ...and to the concrete type's constructor parameters: 147 * 148 * <pre>public class RealPayment implements Payment { 149 * {@literal @}Inject 150 * public RealPayment( 151 * CreditService creditService, 152 * AuthService authService, 153 * <strong>{@literal @}Assisted("startDate")</strong> Date startDate, 154 * <strong>{@literal @}Assisted("dueDate")</strong> Date dueDate, 155 * <strong>{@literal @}Assisted</strong> Money amount) { 156 * ... 157 * } 158 * }</pre> 159 * 160 * <h3>Values are created by Guice</h3> 161 * Returned factories use child injectors to create values. The values are eligible for method 162 * interception. In addition, {@literal @}{@literal Inject} members will be injected before they are 163 * returned. 164 * 165 * <h3>More configuration options</h3> 166 * In addition to simply specifying an implementation class for any returned type, factories' return 167 * values can be automatic or can be configured to use annotations: 168 * <p/> 169 * If you just want to return the types specified in the factory, do not configure any 170 * implementations: 171 * 172 * <pre>public interface FruitFactory { 173 * Apple getApple(Color color); 174 * } 175 * ... 176 * protected void configure() { 177 * install(new FactoryModuleBuilder().build(FruitFactory.class)); 178 * }</pre> 179 * 180 * Note that any type returned by the factory in this manner needs to be an implementation class. 181 * <p/> 182 * To return two different implementations for the same interface from your factory, use binding 183 * annotations on your return types: 184 * 185 * <pre>interface CarFactory { 186 * {@literal @}Named("fast") Car getFastCar(Color color); 187 * {@literal @}Named("clean") Car getCleanCar(Color color); 188 * } 189 * ... 190 * protected void configure() { 191 * install(new FactoryModuleBuilder() 192 * .implement(Car.class, Names.named("fast"), Porsche.class) 193 * .implement(Car.class, Names.named("clean"), Prius.class) 194 * .build(CarFactory.class)); 195 * }</pre> 196 * 197 * <h3>Implementation limitations</h3> 198 * As a limitation of the implementation, it is prohibited to declare a factory method that 199 * accepts a {@code Provider} as one of its arguments. 200 * 201 * @since 3.0 202 * @author schmitt@google.com (Peter Schmitt) 203 */ 204 public final class FactoryModuleBuilder { 205 206 private final BindingCollector bindings = new BindingCollector(); 207 208 /** 209 * See the factory configuration examples at {@link FactoryModuleBuilder}. 210 */ implement(Class<T> source, Class<? extends T> target)211 public <T> FactoryModuleBuilder implement(Class<T> source, Class<? extends T> target) { 212 return implement(source, TypeLiteral.get(target)); 213 } 214 215 /** 216 * See the factory configuration examples at {@link FactoryModuleBuilder}. 217 */ implement(Class<T> source, TypeLiteral<? extends T> target)218 public <T> FactoryModuleBuilder implement(Class<T> source, TypeLiteral<? extends T> target) { 219 return implement(TypeLiteral.get(source), target); 220 } 221 222 /** 223 * See the factory configuration examples at {@link FactoryModuleBuilder}. 224 */ implement(TypeLiteral<T> source, Class<? extends T> target)225 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Class<? extends T> target) { 226 return implement(source, TypeLiteral.get(target)); 227 } 228 229 /** 230 * See the factory configuration examples at {@link FactoryModuleBuilder}. 231 */ implement(TypeLiteral<T> source, TypeLiteral<? extends T> target)232 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, 233 TypeLiteral<? extends T> target) { 234 return implement(Key.get(source), target); 235 } 236 237 /** 238 * See the factory configuration examples at {@link FactoryModuleBuilder}. 239 */ implement(Class<T> source, Annotation annotation, Class<? extends T> target)240 public <T> FactoryModuleBuilder implement(Class<T> source, Annotation annotation, 241 Class<? extends T> target) { 242 return implement(source, annotation, TypeLiteral.get(target)); 243 } 244 245 /** 246 * See the factory configuration examples at {@link FactoryModuleBuilder}. 247 */ implement(Class<T> source, Annotation annotation, TypeLiteral<? extends T> target)248 public <T> FactoryModuleBuilder implement(Class<T> source, Annotation annotation, 249 TypeLiteral<? extends T> target) { 250 return implement(TypeLiteral.get(source), annotation, target); 251 } 252 253 /** 254 * See the factory configuration examples at {@link FactoryModuleBuilder}. 255 */ implement(TypeLiteral<T> source, Annotation annotation, Class<? extends T> target)256 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Annotation annotation, 257 Class<? extends T> target) { 258 return implement(source, annotation, TypeLiteral.get(target)); 259 } 260 261 /** 262 * See the factory configuration examples at {@link FactoryModuleBuilder}. 263 */ implement(TypeLiteral<T> source, Annotation annotation, TypeLiteral<? extends T> target)264 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, Annotation annotation, 265 TypeLiteral<? extends T> target) { 266 return implement(Key.get(source, annotation), target); 267 } 268 269 /** 270 * See the factory configuration examples at {@link FactoryModuleBuilder}. 271 */ implement(Class<T> source, Class<? extends Annotation> annotationType, Class<? extends T> target)272 public <T> FactoryModuleBuilder implement(Class<T> source, 273 Class<? extends Annotation> annotationType, Class<? extends T> target) { 274 return implement(source, annotationType, TypeLiteral.get(target)); 275 } 276 277 /** 278 * See the factory configuration examples at {@link FactoryModuleBuilder}. 279 */ implement(Class<T> source, Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target)280 public <T> FactoryModuleBuilder implement(Class<T> source, 281 Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target) { 282 return implement(TypeLiteral.get(source), annotationType, target); 283 } 284 285 /** 286 * See the factory configuration examples at {@link FactoryModuleBuilder}. 287 */ implement(TypeLiteral<T> source, Class<? extends Annotation> annotationType, Class<? extends T> target)288 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, 289 Class<? extends Annotation> annotationType, Class<? extends T> target) { 290 return implement(source, annotationType, TypeLiteral.get(target)); 291 } 292 293 /** 294 * See the factory configuration examples at {@link FactoryModuleBuilder}. 295 */ implement(TypeLiteral<T> source, Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target)296 public <T> FactoryModuleBuilder implement(TypeLiteral<T> source, 297 Class<? extends Annotation> annotationType, TypeLiteral<? extends T> target) { 298 return implement(Key.get(source, annotationType), target); 299 } 300 301 /** 302 * See the factory configuration examples at {@link FactoryModuleBuilder}. 303 */ implement(Key<T> source, Class<? extends T> target)304 public <T> FactoryModuleBuilder implement(Key<T> source, Class<? extends T> target) { 305 return implement(source, TypeLiteral.get(target)); 306 } 307 308 /** 309 * See the factory configuration examples at {@link FactoryModuleBuilder}. 310 */ implement(Key<T> source, TypeLiteral<? extends T> target)311 public <T> FactoryModuleBuilder implement(Key<T> source, TypeLiteral<? extends T> target) { 312 bindings.addBinding(source, target); 313 return this; 314 } 315 316 /** 317 * See the factory configuration examples at {@link FactoryModuleBuilder}. 318 */ build(Class<F> factoryInterface)319 public <F> Module build(Class<F> factoryInterface) { 320 return build(TypeLiteral.get(factoryInterface)); 321 } 322 323 /** 324 * See the factory configuration examples at {@link FactoryModuleBuilder}. 325 */ build(TypeLiteral<F> factoryInterface)326 public <F> Module build(TypeLiteral<F> factoryInterface) { 327 return build(Key.get(factoryInterface)); 328 } 329 330 build(final Key<F> factoryInterface)331 public <F> Module build(final Key<F> factoryInterface) { 332 return new AbstractModule() { 333 @Override protected void configure() { 334 Provider<F> provider = new FactoryProvider2<F>(factoryInterface, bindings); 335 bind(factoryInterface).toProvider(provider); 336 } 337 }; 338 } 339 } 340