Author: limpbizkit
Date: Tue Oct 14 17:06:43 2008
New Revision: 631
Modified:
trunk/src/com/google/inject/Initializer.java
Log:
Initializer cleanup. Now each InjectableReference takes care of itself,
which should make the code a bit simpler to use.
Modified: trunk/src/com/google/inject/Initializer.java
==============================================================================
--- trunk/src/com/google/inject/Initializer.java (original)
+++ trunk/src/com/google/inject/Initializer.java Tue Oct 14 17:06:43 2008
@@ -17,17 +17,19 @@
package com.google.inject;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
import com.google.inject.spi.InjectionPoint;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
/**
- * Manages and injects instances at injector-creation time.
+ * Manages and injects instances at injector-creation time. This is made
more complicated by
+ * instances that request other instances while they're being injected. We
overcome this by using
+ * [EMAIL PROTECTED] Initializable}, which attempts to perform injection
before use.
*
* @author [EMAIL PROTECTED] (Jesse Wilson)
*/
@@ -39,7 +41,7 @@
private final CountDownLatch ready = new CountDownLatch(1);
/** Maps instances that need injection to a source that registered them
*/
- private final Map<Object, Object> outstandingInjections =
Maps.newIdentityHashMap();
+ private final Map<Object, InjectableReference<?>> pendingInjection =
Maps.newIdentityHashMap();
private final InjectorImpl injector;
Initializer(InjectorImpl injector) {
@@ -56,8 +58,15 @@
public <T> Initializable<T> requestInjection(T instance, Object source,
Set<InjectionPoint> injectionPoints) {
checkNotNull(source);
- outstandingInjections.put(instance, source);
- return new InjectableReference<T>(this, instance);
+
+ // short circuit if the object doesn't have any @Inject members
+ if (injectionPoints.isEmpty()) {
+ return Initializables.of(instance);
+ }
+
+ InjectableReference<T> initializable = new
InjectableReference<T>(instance, source);
+ pendingInjection.put(instance, initializable);
+ return initializable;
}
/**
@@ -65,11 +74,9 @@
* on the injected instances.
*/
void validateOustandingInjections(Errors errors) {
- for (Map.Entry<Object, Object> entry :
outstandingInjections.entrySet()) {
+ for (InjectableReference<?> reference : pendingInjection.values()) {
try {
- Object toInject = entry.getKey();
- Object source = entry.getValue();
- injector.injectors.get(toInject.getClass(),
errors.withSource(source));
+ reference.validate(errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
@@ -78,82 +85,70 @@
/**
* Performs creation-time injections on all objects that require it.
Whenever fulfilling an
- * injection depends on another object that requires injection, we use
[EMAIL PROTECTED]
- * #ensureInjected(Object,com.google.inject.internal.Errors)} to inject
that member first.
- *
- * <p>If the two objects are codependent (directly or transitively),
ordering of injection is
- * arbitrary.
+ * injection depends on another object that requires injection, we
inject it first. If the two
+ * instances are codependent (directly or transitively), ordering of
injection is arbitrary.
*/
void injectAll(final Errors errors) {
// loop over a defensive copy since ensureInjected() mutates the set.
Unfortunately, that copy
// is made complicated by a bug in IBM's JDK, wherein
entrySet().toArray(Object[]) doesn't work
- for (Object entryObject : outstandingInjections.entrySet().toArray()) {
- @SuppressWarnings("unchecked")
- Entry<Object, Object> entry = (Entry<Object, Object>) entryObject;
+ for (InjectableReference<?> reference :
Lists.newArrayList(pendingInjection.values())) {
try {
- Object toInject = entry.getKey();
- Object source = entry.getValue();
- ensureInjected(toInject, errors.withSource(source));
+ reference.get(errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
}
- if (!outstandingInjections.isEmpty()) {
- throw new AssertionError("Failed to satisfy " +
outstandingInjections);
+ if (!pendingInjection.isEmpty()) {
+ throw new AssertionError("Failed to satisfy " + pendingInjection);
}
ready.countDown();
}
private class InjectableReference<T> implements Initializable<T> {
- private final Initializer initializer;
private final T instance;
+ private final Object source;
- public InjectableReference(Initializer initializer, T instance) {
- this.initializer = checkNotNull(initializer, "initializer");
+ public InjectableReference(T instance, Object source) {
this.instance = checkNotNull(instance, "instance");
+ this.source = checkNotNull(source, "source");
+ }
+
+ public void validate(Errors errors) throws ErrorsException {
+ injector.injectors.get(instance.getClass(),
errors.withSource(source));
}
/**
- * Ensures that the instance has been injected, and returns it.
+ * Reentrant. If [EMAIL PROTECTED] instance} was registered for injection
at
injector-creation time, this
+ * method will ensure that all its members have been injected before
returning.
*/
public T get(Errors errors) throws ErrorsException {
- initializer.ensureInjected(instance, errors);
- return instance;
- }
-
- @Override public String toString() {
- return instance.toString();
- }
- }
-
+ if (ready.getCount() == 0) {
+ return instance;
+ }
- /**
- * Reentrant. If [EMAIL PROTECTED] toInject} was registered for injection at
injector-creation time, this
- * method will ensure that all its members have been injected before
returning. This method is
- * used both internally, and by [EMAIL PROTECTED] InternalContext} to
satisfy
injections while satisfying
- * other injections.
- */
- void ensureInjected(Object toInject, Errors errors) throws
ErrorsException {
- if (ready.getCount() == 0) {
- return;
- }
+ // just wait for everything to be injected by another thread
+ if (Thread.currentThread() != creatingThread) {
+ try {
+ ready.await();
+ return instance;
+ } catch (InterruptedException e) {
+ // Give up, since we don't know if our injection is ready
+ throw new RuntimeException(e);
+ }
+ }
- // just wait for everything to be injected by another thread
- if (Thread.currentThread() != creatingThread) {
- try {
- ready.await();
- return;
- } catch (InterruptedException e) {
- // Give up, since we don't know if our injection is ready
- throw new RuntimeException(e);
+ // toInject needs injection, do it right away
+ if (pendingInjection.remove(instance) != null) {
+ injector.injectMembersOrThrow(errors.withSource(source), instance);
}
+
+ return instance;
}
- // toInject needs injection, do it right away
- if (outstandingInjections.remove(toInject) != null) {
- injector.injectMembersOrThrow(errors, toInject);
+ @Override public String toString() {
+ return instance.toString();
}
}
}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---