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