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