• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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