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