Created
July 7, 2014 18:12
-
-
Save gissuebot/2af8db53bba2d4506915 to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 342, comment 5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: test/com/google/inject/JitBindingsTest.java | |
=================================================================== | |
--- test/com/google/inject/JitBindingsTest.java (revision 0) | |
+++ test/com/google/inject/JitBindingsTest.java (revision 0) | |
@@ -0,0 +1,165 @@ | |
+package com.google.inject; | |
+ | |
+import junit.framework.TestCase; | |
+ | |
+public class JitBindingsTest extends TestCase { | |
+ | |
+ private String jitFailed(Class<?> clazz) { | |
+ return jitFailed(TypeLiteral.get(clazz)); | |
+ } | |
+ | |
+ private String jitFailed(TypeLiteral<?> clazz) { | |
+ return "Just in time binding is disabled, and " + clazz + " is not explicitly bound."; | |
+ } | |
+ | |
+ public void testLinkedBindingWorks() { | |
+ Injector injector = Guice.createInjectorBuilder().disableJit(true).addModules(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bind(Foo.class).to(FooImpl.class); | |
+ } | |
+ }).build(); | |
+ injector.getInstance(Foo.class); | |
+ | |
+ try { | |
+ injector.getInstance(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ try { | |
+ injector.getProvider(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testMoreBasicsWork() { | |
+ Injector injector = Guice.createInjectorBuilder().disableJit(true).addModules(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bind(Foo.class).to(FooImpl.class); | |
+ bind(Bar.class); | |
+ bind(FooBar.class); | |
+ } | |
+ }).build(); | |
+ injector.getInstance(FooBar.class); | |
+ injector.getInstance(Bar.class); | |
+ injector.getInstance(Foo.class); | |
+ try { | |
+ injector.getInstance(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ try { | |
+ injector.getProvider(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testLinkedProviderBindingWorks() { | |
+ Injector injector = Guice.createInjectorBuilder().disableJit(true).addModules(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bind(Foo.class).toProvider(FooImplProvider.class); | |
+ } | |
+ }).build(); | |
+ injector.getInstance(Foo.class); | |
+ | |
+ try { | |
+ injector.getInstance(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ try { | |
+ injector.getProvider(FooImpl.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testJitGetFails() { | |
+ try { | |
+ Guice.createInjectorBuilder().disableJit(true).build().getInstance(Bar.class); | |
+ fail("should have failed"); | |
+ } catch(ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testJitInjectionFails() { | |
+ try { | |
+ Guice.createInjectorBuilder().disableJit(true).addModules(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bind(Foo.class).to(FooImpl.class); | |
+ bind(FooBar.class); | |
+ } | |
+ }).build(); | |
+ fail("should have failed"); | |
+ } catch (CreationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testJitProviderGetFails() { | |
+ try { | |
+ Guice.createInjectorBuilder().disableJit(true).build().getProvider(Bar.class); | |
+ fail("should have failed"); | |
+ } catch (ConfigurationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ public void testJitProviderInjectionFails() { | |
+ try { | |
+ Guice.createInjectorBuilder().disableJit(true).addModules(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bind(Foo.class).to(FooImpl.class); | |
+ bind(ProviderFooBar.class); | |
+ } | |
+ }).build(); | |
+ fail("should have failed"); | |
+ } catch (CreationException expected) { | |
+ Asserts.assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); | |
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2)")); | |
+ } | |
+ } | |
+ | |
+ | |
+ private static interface Foo {} | |
+ private static class FooImpl implements Foo {} | |
+ private static class Bar {} | |
+ private static class FooBar { | |
+ @Inject Foo foo; | |
+ @Inject Bar bar; | |
+ } | |
+ private static class ProviderFooBar { | |
+ @Inject Provider<Foo> foo; | |
+ @Inject Provider<Bar> bar; | |
+ } | |
+ private static class FooImplProvider implements Provider<Foo> { | |
+ @Override | |
+ public Foo get() { | |
+ return new FooImpl(); | |
+ } | |
+ } | |
+ | |
+ | |
+} | |
Index: test/com/google/inject/ReflectionTest.java | |
=================================================================== | |
--- test/com/google/inject/ReflectionTest.java (revision 1113) | |
+++ test/com/google/inject/ReflectionTest.java (working copy) | |
@@ -16,11 +16,14 @@ | |
package com.google.inject; | |
+import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
+ | |
import java.lang.annotation.Retention; | |
-import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
+ | |
import junit.framework.TestCase; | |
-import com.google.inject.internal.InjectorBuilder; | |
+import com.google.inject.internal.InjectorBuilderImpl; | |
+ | |
/** | |
* @author crazybob@google.com (Bob Lee) | |
*/ | |
@@ -30,7 +33,7 @@ | |
@BindingAnnotation @interface I {} | |
public void testNormalBinding() throws CreationException { | |
- InjectorBuilder builder = new InjectorBuilder(); | |
+ InjectorBuilder builder = new InjectorBuilderImpl(); | |
final Foo foo = new Foo(); | |
Injector injector = Guice.createInjector(new AbstractModule() { | |
@@ -59,7 +62,7 @@ | |
} | |
public void testLinkedBinding() throws CreationException { | |
- InjectorBuilder builder = new InjectorBuilder(); | |
+ InjectorBuilder builder = new InjectorBuilderImpl(); | |
final Bar bar = new Bar(); | |
Injector injector = Guice.createInjector(new AbstractModule() { | |
Index: src/com/google/inject/InjectorBuilder.java | |
=================================================================== | |
--- src/com/google/inject/InjectorBuilder.java (revision 0) | |
+++ src/com/google/inject/InjectorBuilder.java (revision 0) | |
@@ -0,0 +1,35 @@ | |
+package com.google.inject; | |
+ | |
+/** | |
+ * Allows Injectors to be built with many different parameters. | |
+ */ | |
+public interface InjectorBuilder { | |
+ | |
+ /** | |
+ * Sets the stage for the created injector. If the stage is {@link Stage#PRODUCTION}, | |
+ * singletons will be eagerly loaded in when the Injector is built. | |
+ */ | |
+ InjectorBuilder stage(Stage stage); | |
+ | |
+ /** | |
+ * If just-in-time binding is disabled, then classes cannot inject classes | |
+ * that are not explicitly bound in a module. | |
+ * | |
+ * Tools can still retrieve bindings for implicit bindings (bindings created | |
+ * through a linked binding) if jit binding is disabled, however they will be | |
+ * unable to retrieve an instance of the binding. | |
+ * | |
+ * By default, JIT binding is enabled. | |
+ */ | |
+ InjectorBuilder disableJit(boolean jitDisabled); | |
+ | |
+ /** Adds more modules that will be used when the Injector is created. */ | |
+ InjectorBuilder addModules(Iterable<? extends Module> modules); | |
+ | |
+ /** Adds more modules that will be used when the Injector is created. */ | |
+ InjectorBuilder addModules(Module... modules); | |
+ | |
+ /** Builds the injector. */ | |
+ Injector build(); | |
+ | |
+} | |
\ No newline at end of file | |
Index: src/com/google/inject/internal/InternalFactory.java | |
=================================================================== | |
--- src/com/google/inject/internal/InternalFactory.java (revision 1113) | |
+++ src/com/google/inject/internal/InternalFactory.java (working copy) | |
@@ -27,11 +27,12 @@ | |
/** | |
* Creates an object to be injected. | |
+ * @param context of this injection | |
+ * @param linked true if getting as a result of a linked binding | |
* | |
- * @param context of this injection | |
* @throws com.google.inject.internal.ErrorsException if a value cannot be provided | |
* @return instance to be injected | |
*/ | |
- T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException; | |
} | |
Index: src/com/google/inject/internal/BindingProcessor.java | |
=================================================================== | |
--- src/com/google/inject/internal/BindingProcessor.java (revision 1113) | |
+++ src/com/google/inject/internal/BindingProcessor.java (working copy) | |
@@ -88,7 +88,7 @@ | |
public Void visit(ConstructorBinding<? extends T> binding) { | |
try { | |
ConstructorBindingImpl<T> onInjector = ConstructorBindingImpl.create(injector, key, | |
- binding.getConstructor(), source, scoping, errors); | |
+ binding.getConstructor(), source, scoping, errors, false); | |
scheduleInitialization(onInjector); | |
putBinding(onInjector); | |
} catch (ErrorsException e) { | |
@@ -165,7 +165,7 @@ | |
// This cast is safe after the preceeding check. | |
try { | |
BindingImpl<T> binding = injector.createUninitializedBinding( | |
- key, scoping, source, errors); | |
+ key, scoping, source, errors, false); | |
scheduleInitialization(binding); | |
putBinding(binding); | |
} catch (ErrorsException e) { | |
Index: src/com/google/inject/internal/Errors.java | |
=================================================================== | |
--- src/com/google/inject/internal/Errors.java (revision 1113) | |
+++ src/com/google/inject/internal/Errors.java (working copy) | |
@@ -124,6 +124,10 @@ | |
public Errors missingImplementation(Key key) { | |
return addMessage("No implementation for %s was bound.", key); | |
} | |
+ | |
+ public Errors jitDisabled(Key key) { | |
+ return addMessage("Just in time binding is disabled, and %s is not explicitly bound.", key); | |
+ } | |
public Errors converterReturnedNull(String stringValue, Object source, | |
TypeLiteral<?> type, MatcherAndConverter matchingConverter) { | |
Index: src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java | |
=================================================================== | |
--- src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java (revision 1113) | |
+++ src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java (working copy) | |
@@ -40,7 +40,7 @@ | |
T t = injector.callInContext(new ContextualCallable<T>() { | |
public T call(InternalContext context) throws ErrorsException { | |
Dependency dependency = context.getDependency(); | |
- return internalFactory.get(errors, context, dependency); | |
+ return internalFactory.get(errors, context, dependency, false); | |
} | |
}); | |
errors.throwIfNewErrors(0); | |
Index: src/com/google/inject/internal/InjectorImpl.java | |
=================================================================== | |
--- src/com/google/inject/internal/InjectorImpl.java (revision 1113) | |
+++ src/com/google/inject/internal/InjectorImpl.java (working copy) | |
@@ -21,6 +21,7 @@ | |
import com.google.inject.ConfigurationException; | |
import com.google.inject.ImplementedBy; | |
import com.google.inject.Injector; | |
+import com.google.inject.InjectorBuilder; | |
import com.google.inject.Key; | |
import com.google.inject.MembersInjector; | |
import com.google.inject.Module; | |
@@ -60,16 +61,18 @@ | |
final InjectorImpl parent; | |
final BindingsMultimap bindingsMultimap = new BindingsMultimap(); | |
final Initializer initializer; | |
+ final boolean jitDisabled; | |
/** Just-in-time binding cache. Guarded by state.lock() */ | |
final Map<Key<?>, BindingImpl<?>> jitBindings = Maps.newHashMap(); | |
Lookups lookups = new DeferredLookups(this); | |
- InjectorImpl(@Nullable InjectorImpl parent, State state, Initializer initializer) { | |
+ InjectorImpl(@Nullable InjectorImpl parent, State state, Initializer initializer, boolean jitDisabled) { | |
this.parent = parent; | |
this.state = state; | |
this.initializer = initializer; | |
+ this.jitDisabled = jitDisabled; | |
if (parent != null) { | |
localContext = parent.localContext; | |
@@ -101,7 +104,7 @@ | |
public <T> BindingImpl<T> getBinding(Key<T> key) { | |
Errors errors = new Errors(key); | |
try { | |
- BindingImpl<T> result = getBindingOrThrow(key, errors); | |
+ BindingImpl<T> result = getBindingOrThrow(key, errors, true); | |
errors.throwConfigurationExceptionIfErrorsExist(); | |
return result; | |
} catch (ErrorsException e) { | |
@@ -115,7 +118,7 @@ | |
* checks for an explicit binding. If no explicit binding is found, it looks for a just-in-time | |
* binding. | |
*/ | |
- <T> BindingImpl<T> getBindingOrThrow(Key<T> key, Errors errors) | |
+ <T> BindingImpl<T> getBindingOrThrow(Key<T> key, Errors errors, boolean allowJit) | |
throws ErrorsException { | |
// Check explicit bindings, i.e. bindings created by modules. | |
BindingImpl<T> binding = state.getExplicitBinding(key); | |
@@ -124,7 +127,7 @@ | |
} | |
// Look for an on-demand binding. | |
- return getJustInTimeBinding(key, errors); | |
+ return getJustInTimeBinding(key, errors, allowJit); | |
} | |
public <T> Binding<T> getBinding(Class<T> type) { | |
@@ -136,7 +139,7 @@ | |
} | |
public Injector createChildInjector(Iterable<? extends Module> modules) { | |
- return new InjectorBuilder() | |
+ return new InjectorBuilderImpl() | |
.parentInjector(this) | |
.addModules(modules) | |
.build(); | |
@@ -145,14 +148,26 @@ | |
public Injector createChildInjector(Module... modules) { | |
return createChildInjector(ImmutableList.of(modules)); | |
} | |
+ | |
+ @Override | |
+ public InjectorBuilder createChildInjectorBuilder() { | |
+ return new InjectorBuilderImpl() | |
+ .parentInjector(this); | |
+ } | |
/** | |
* Returns a just-in-time binding for {@code key}, creating it if necessary. | |
* | |
* @throws ErrorsException if the binding could not be created. | |
*/ | |
- private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors) | |
+ private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors, boolean allowJit) | |
throws ErrorsException { | |
+ | |
+ | |
+ if(!isProvider(key) && !allowJit && jitDisabled) { | |
+ throw errors.jitDisabled(key).toException(); | |
+ } | |
+ | |
synchronized (state.lock()) { | |
// first try to find a JIT binding that we've already created | |
for (InjectorImpl injector = this; injector != null; injector = injector.parent) { | |
@@ -163,7 +178,7 @@ | |
return binding; | |
} | |
} | |
- | |
+ | |
return createJustInTimeBindingRecursive(key, errors); | |
} | |
} | |
@@ -217,7 +232,7 @@ | |
@SuppressWarnings("unchecked") // safe because T came from Key<Provider<T>> | |
Key<T> providedKey = (Key<T>) key.ofType(entryType); | |
- BindingImpl<T> delegate = getBindingOrThrow(providedKey, errors); | |
+ BindingImpl<T> delegate = getBindingOrThrow(providedKey, errors, false); | |
return new ProviderBindingImpl<T>(this, key, delegate); | |
} | |
@@ -234,7 +249,7 @@ | |
static <T> InternalFactory<Provider<T>> createInternalFactory(Binding<T> providedBinding) { | |
final Provider<T> provider = providedBinding.getProvider(); | |
return new InternalFactory<Provider<T>>() { | |
- public Provider<T> get(Errors errors, InternalContext context, Dependency dependency) { | |
+ public Provider<T> get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { | |
return provider; | |
} | |
}; | |
@@ -394,7 +409,7 @@ | |
* none is specified. | |
*/ | |
<T> BindingImpl<T> createUninitializedBinding(Key<T> key, Scoping scoping, Object source, | |
- Errors errors) throws ErrorsException { | |
+ Errors errors, boolean jitBinding) throws ErrorsException { | |
Class<?> rawType = key.getTypeLiteral().getRawType(); | |
// Don't try to inject arrays, or enums. | |
@@ -424,7 +439,8 @@ | |
return createProvidedByBinding(key, scoping, providedBy, errors); | |
} | |
- return ConstructorBindingImpl.create(this, key, null, source, scoping, errors); | |
+ | |
+ return ConstructorBindingImpl.create(this, key, null, source, scoping, errors, jitBinding && jitDisabled); | |
} | |
/** | |
@@ -473,14 +489,14 @@ | |
final Key<? extends Provider<T>> providerKey | |
= (Key<? extends Provider<T>>) Key.get(providerType); | |
final BindingImpl<? extends Provider<?>> providerBinding | |
- = getBindingOrThrow(providerKey, errors); | |
+ = getBindingOrThrow(providerKey, errors, false); | |
InternalFactory<T> internalFactory = new InternalFactory<T>() { | |
- public T get(Errors errors, InternalContext context, Dependency dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) | |
throws ErrorsException { | |
errors = errors.withSource(providerKey); | |
Provider<?> provider = providerBinding.getInternalFactory().get( | |
- errors, context, dependency); | |
+ errors, context, dependency, linked); | |
try { | |
Object o = provider.get(); | |
if (o != null && !rawType.isInstance(o)) { | |
@@ -527,13 +543,13 @@ | |
// Look up the target binding. | |
final Key<? extends T> targetKey = Key.get(subclass); | |
- final BindingImpl<? extends T> targetBinding = getBindingOrThrow(targetKey, errors); | |
+ final BindingImpl<? extends T> targetBinding = getBindingOrThrow(targetKey, errors, false); | |
InternalFactory<T> internalFactory = new InternalFactory<T>() { | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
return targetBinding.getInternalFactory().get( | |
- errors.withSource(targetKey), context, dependency); | |
+ errors.withSource(targetKey), context, dependency, false); | |
} | |
}; | |
@@ -554,7 +570,7 @@ | |
private <T> BindingImpl<T> createJustInTimeBindingRecursive(Key<T> key, Errors errors) | |
throws ErrorsException { | |
// ask the parent to create the JIT binding | |
- if (parent != null) { | |
+ if (parent != null && !parent.jitDisabled) { | |
try { | |
return parent.createJustInTimeBindingRecursive(key, new Errors()); | |
} catch (ErrorsException ignored) { | |
@@ -622,7 +638,7 @@ | |
if (key.hasAttributes()) { | |
try { | |
Errors ignored = new Errors(); | |
- return getBindingOrThrow(key.withoutAttributes(), ignored); | |
+ return getBindingOrThrow(key.withoutAttributes(), ignored, false); | |
} catch (ErrorsException ignored) { | |
// throw with a more appropriate message below | |
} | |
@@ -631,15 +647,15 @@ | |
} | |
Object source = key.getTypeLiteral().getRawType(); | |
- BindingImpl<T> binding = createUninitializedBinding(key, Scoping.UNSCOPED, source, errors); | |
+ BindingImpl<T> binding = createUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true); | |
errors.throwIfNewErrors(numErrorsBefore); | |
initializeJitBinding(binding, errors); | |
return binding; | |
} | |
- <T> InternalFactory<? extends T> getInternalFactory(Key<T> key, Errors errors) | |
+ <T> InternalFactory<? extends T> getInternalFactory(Key<T> key, Errors errors, boolean allowJit) | |
throws ErrorsException { | |
- return getBindingOrThrow(key, errors).getInternalFactory(); | |
+ return getBindingOrThrow(key, errors, allowJit).getInternalFactory(); | |
} | |
public Map<Key<?>, Binding<?>> getBindings() { | |
@@ -707,7 +723,7 @@ | |
<T> SingleParameterInjector<T> createParameterInjector(final Dependency<T> dependency, | |
final Errors errors) throws ErrorsException { | |
- InternalFactory<? extends T> factory = getInternalFactory(dependency.getKey(), errors); | |
+ InternalFactory<? extends T> factory = getInternalFactory(dependency.getKey(), errors, false); | |
return new SingleParameterInjector<T>(dependency, factory); | |
} | |
@@ -747,7 +763,9 @@ | |
} | |
<T> Provider<T> getProviderOrThrow(final Key<T> key, Errors errors) throws ErrorsException { | |
- final InternalFactory<? extends T> factory = getInternalFactory(key, errors); | |
+ | |
+ | |
+ final InternalFactory<? extends T> factory = getInternalFactory(key, errors, false); | |
final Dependency<T> dependency = Dependency.get(key); | |
return new Provider<T>() { | |
@@ -758,7 +776,7 @@ | |
public T call(InternalContext context) throws ErrorsException { | |
Dependency previous = context.setDependency(dependency); | |
try { | |
- return factory.get(errors, context, dependency); | |
+ return factory.get(errors, context, dependency, false); | |
} finally { | |
context.setDependency(previous); | |
} | |
Index: src/com/google/inject/internal/UntargettedBindingImpl.java | |
=================================================================== | |
--- src/com/google/inject/internal/UntargettedBindingImpl.java (revision 1113) | |
+++ src/com/google/inject/internal/UntargettedBindingImpl.java (working copy) | |
@@ -26,7 +26,7 @@ | |
UntargettedBindingImpl(InjectorImpl injector, Key<T> key, Object source) { | |
super(injector, key, source, new InternalFactory<T>() { | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) { | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) { | |
throw new AssertionError(); | |
} | |
}, Scoping.UNSCOPED); | |
Index: src/com/google/inject/internal/InjectorShell.java | |
=================================================================== | |
--- src/com/google/inject/internal/InjectorShell.java (revision 1113) | |
+++ src/com/google/inject/internal/InjectorShell.java (working copy) | |
@@ -70,6 +70,7 @@ | |
private InjectorImpl parent; | |
private Stage stage; | |
+ private boolean jitDisabled; | |
/** null unless this exists in a {@link Binder#newPrivateBinder private environment} */ | |
private PrivateElementsImpl privateElements; | |
@@ -84,6 +85,11 @@ | |
this.stage = stage; | |
return this; | |
} | |
+ | |
+ Builder jitDisabled(boolean jitDisabled) { | |
+ this.jitDisabled = jitDisabled; | |
+ return this; | |
+ } | |
Builder privateElements(PrivateElements privateElements) { | |
this.privateElements = (PrivateElementsImpl) privateElements; | |
@@ -113,7 +119,7 @@ | |
checkState(privateElements == null || parent != null, "PrivateElements with no parent"); | |
checkState(state != null, "no state. Did you remember to lock() ?"); | |
- InjectorImpl injector = new InjectorImpl(parent, state, initializer); | |
+ InjectorImpl injector = new InjectorImpl(parent, state, initializer, jitDisabled); | |
if (privateElements != null) { | |
privateElements.initInjector(injector); | |
} | |
@@ -193,7 +199,7 @@ | |
this.injector = injector; | |
} | |
- public Injector get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public Injector get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
return injector; | |
} | |
@@ -221,7 +227,7 @@ | |
} | |
private static class LoggerFactory implements InternalFactory<Logger>, Provider<Logger> { | |
- public Logger get(Errors errors, InternalContext context, Dependency<?> dependency) { | |
+ public Logger get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) { | |
InjectionPoint injectionPoint = dependency.getInjectionPoint(); | |
return injectionPoint == null | |
? Logger.getAnonymousLogger() | |
Index: src/com/google/inject/internal/ExposedKeyFactory.java | |
=================================================================== | |
--- src/com/google/inject/internal/ExposedKeyFactory.java (revision 1113) | |
+++ src/com/google/inject/internal/ExposedKeyFactory.java (working copy) | |
@@ -49,8 +49,8 @@ | |
this.delegate = explicitBinding; | |
} | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
- return delegate.getInternalFactory().get(errors, context, dependency); | |
+ return delegate.getInternalFactory().get(errors, context, dependency, linked); | |
} | |
} | |
Index: src/com/google/inject/internal/SingleParameterInjector.java | |
=================================================================== | |
--- src/com/google/inject/internal/SingleParameterInjector.java (revision 1113) | |
+++ src/com/google/inject/internal/SingleParameterInjector.java (working copy) | |
@@ -35,7 +35,7 @@ | |
private T inject(Errors errors, InternalContext context) throws ErrorsException { | |
Dependency previous = context.setDependency(dependency); | |
try { | |
- return factory.get(errors.withSource(dependency), context, dependency); | |
+ return factory.get(errors.withSource(dependency), context, dependency, false); | |
} finally { | |
context.setDependency(previous); | |
} | |
Index: src/com/google/inject/internal/InjectorBuilderImpl.java | |
=================================================================== | |
--- src/com/google/inject/internal/InjectorBuilderImpl.java (revision 1113) | |
+++ src/com/google/inject/internal/InjectorBuilderImpl.java (working copy) | |
@@ -18,6 +18,7 @@ | |
import com.google.inject.Binding; | |
import com.google.inject.Injector; | |
+import com.google.inject.InjectorBuilder; | |
import com.google.inject.Key; | |
import com.google.inject.MembersInjector; | |
import com.google.inject.Module; | |
@@ -26,6 +27,8 @@ | |
import com.google.inject.TypeLiteral; | |
import com.google.inject.Scope; | |
import com.google.inject.spi.Dependency; | |
+ | |
+import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.Map; | |
@@ -51,7 +54,7 @@ | |
* @author crazybob@google.com (Bob Lee) | |
* @author jessewilson@google.com (Jesse Wilson) | |
*/ | |
-public final class InjectorBuilder { | |
+public final class InjectorBuilderImpl implements com.google.inject.InjectorBuilder { | |
private final Stopwatch stopwatch = new Stopwatch(); | |
private final Errors errors = new Errors(); | |
@@ -65,20 +68,21 @@ | |
private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder(); | |
private List<InjectorShell> shells; | |
- public InjectorBuilder() { | |
+ public InjectorBuilderImpl() { | |
injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer); | |
bindingProcesor = new BindingProcessor(errors, initializer); | |
} | |
- /** | |
- * Sets the stage for the created injector. If the stage is {@link Stage#PRODUCTION}, this class | |
- * will eagerly load singletons. | |
- */ | |
public InjectorBuilder stage(Stage stage) { | |
shellBuilder.stage(stage); | |
this.stage = stage; | |
return this; | |
} | |
+ | |
+ public InjectorBuilder disableJit(boolean jitDisabled) { | |
+ shellBuilder.jitDisabled(jitDisabled); | |
+ return this; | |
+ } | |
/** | |
* Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's | |
@@ -93,6 +97,12 @@ | |
shellBuilder.addModules(modules); | |
return this; | |
} | |
+ | |
+ @Override | |
+ public InjectorBuilder addModules(Module... modules) { | |
+ shellBuilder.addModules(Arrays.asList(modules)); | |
+ return this; | |
+ } | |
public Injector build() { | |
if (shellBuilder == null) { | |
@@ -200,7 +210,7 @@ | |
Dependency previous = context.setDependency(dependency); | |
Errors errorsForBinding = errors.withSource(dependency); | |
try { | |
- binding.getInternalFactory().get(errorsForBinding, context, dependency); | |
+ binding.getInternalFactory().get(errorsForBinding, context, dependency, false); | |
} catch (ErrorsException e) { | |
errorsForBinding.merge(e.getErrors()); | |
} finally { | |
@@ -268,6 +278,9 @@ | |
public Injector createChildInjector(Module... modules) { | |
return delegateInjector.createChildInjector(modules); | |
} | |
+ public InjectorBuilder createChildInjectorBuilder() { | |
+ return delegateInjector.createChildInjectorBuilder(); | |
+ } | |
public Map<Class<? extends Annotation>, Scope> getScopeBindings() { | |
return delegateInjector.getScopeBindings(); | |
} | |
Index: src/com/google/inject/internal/BoundProviderFactory.java | |
=================================================================== | |
--- src/com/google/inject/internal/BoundProviderFactory.java (revision 1113) | |
+++ src/com/google/inject/internal/BoundProviderFactory.java (working copy) | |
@@ -41,16 +41,16 @@ | |
public void notify(Errors errors) { | |
try { | |
- providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source)); | |
+ providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source), true); | |
} catch (ErrorsException e) { | |
errors.merge(e.getErrors()); | |
} | |
} | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
errors = errors.withSource(providerKey); | |
- javax.inject.Provider<? extends T> provider = providerFactory.get(errors, context, dependency); | |
+ javax.inject.Provider<? extends T> provider = providerFactory.get(errors, context, dependency, true); | |
try { | |
return errors.checkForNull(provider.get(), source, dependency); | |
} catch(RuntimeException userException) { | |
Index: src/com/google/inject/internal/InternalFactoryToProviderAdapter.java | |
=================================================================== | |
--- src/com/google/inject/internal/InternalFactoryToProviderAdapter.java (revision 1113) | |
+++ src/com/google/inject/internal/InternalFactoryToProviderAdapter.java (working copy) | |
@@ -34,7 +34,7 @@ | |
this.source = checkNotNull(source, "source"); | |
} | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
try { | |
return errors.checkForNull(initializable.get(errors).get(), source, dependency); | |
Index: src/com/google/inject/internal/InjectorBuilder.java | |
=================================================================== | |
--- src/com/google/inject/internal/InjectorBuilder.java (revision 1113) | |
+++ src/com/google/inject/internal/InjectorBuilder.java (working copy) | |
@@ -1,299 +0,0 @@ | |
-/** | |
- * Copyright (C) 2006 Google Inc. | |
- * | |
- * Licensed under the Apache License, Version 2.0 (the "License"); | |
- * you may not use this file except in compliance with the License. | |
- * You may obtain a copy of the License at | |
- * | |
- * http://www.apache.org/licenses/LICENSE-2.0 | |
- * | |
- * Unless required by applicable law or agreed to in writing, software | |
- * distributed under the License is distributed on an "AS IS" BASIS, | |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
- * See the License for the specific language governing permissions and | |
- * limitations under the License. | |
- */ | |
- | |
-package com.google.inject.internal; | |
- | |
-import com.google.inject.Binding; | |
-import com.google.inject.Injector; | |
-import com.google.inject.Key; | |
-import com.google.inject.MembersInjector; | |
-import com.google.inject.Module; | |
-import com.google.inject.Provider; | |
-import com.google.inject.Stage; | |
-import com.google.inject.TypeLiteral; | |
-import com.google.inject.Scope; | |
-import com.google.inject.spi.Dependency; | |
-import java.util.Collection; | |
-import java.util.List; | |
-import java.util.Map; | |
-import java.util.Set; | |
-import java.lang.annotation.Annotation; | |
- | |
-/** | |
- * Builds a tree of injectors. This is a primary injector, plus child injectors needed for each | |
- * {@code Binder.newPrivateBinder() private environment}. The primary injector is not necessarily a | |
- * top-level injector. | |
- * | |
- * <p>Injector construction happens in two phases. | |
- * <ol> | |
- * <li>Static building. In this phase, we interpret commands, create bindings, and inspect | |
- * dependencies. During this phase, we hold a lock to ensure consistency with parent injectors. | |
- * No user code is executed in this phase.</li> | |
- * <li>Dynamic injection. In this phase, we call user code. We inject members that requested | |
- * injection. This may require user's objects be created and their providers be called. And we | |
- * create eager singletons. In this phase, user code may have started other threads. This phase | |
- * is not executed for injectors created using {@link Stage#TOOL the tool stage}</li> | |
- * </ol> | |
- * | |
- * @author crazybob@google.com (Bob Lee) | |
- * @author jessewilson@google.com (Jesse Wilson) | |
- */ | |
-public final class InjectorBuilder { | |
- | |
- private final Stopwatch stopwatch = new Stopwatch(); | |
- private final Errors errors = new Errors(); | |
- | |
- private Stage stage; | |
- | |
- private final Initializer initializer = new Initializer(); | |
- private final BindingProcessor bindingProcesor; | |
- private final InjectionRequestProcessor injectionRequestProcessor; | |
- | |
- private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder(); | |
- private List<InjectorShell> shells; | |
- | |
- public InjectorBuilder() { | |
- injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer); | |
- bindingProcesor = new BindingProcessor(errors, initializer); | |
- } | |
- | |
- /** | |
- * Sets the stage for the created injector. If the stage is {@link Stage#PRODUCTION}, this class | |
- * will eagerly load singletons. | |
- */ | |
- public InjectorBuilder stage(Stage stage) { | |
- shellBuilder.stage(stage); | |
- this.stage = stage; | |
- return this; | |
- } | |
- | |
- /** | |
- * Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's | |
- * stage to the stage of {@code parent}. | |
- */ | |
- public InjectorBuilder parentInjector(InjectorImpl parent) { | |
- shellBuilder.parent(parent); | |
- return stage(parent.getInstance(Stage.class)); | |
- } | |
- | |
- public InjectorBuilder addModules(Iterable<? extends Module> modules) { | |
- shellBuilder.addModules(modules); | |
- return this; | |
- } | |
- | |
- public Injector build() { | |
- if (shellBuilder == null) { | |
- throw new AssertionError("Already built, builders are not reusable."); | |
- } | |
- | |
- // Synchronize while we're building up the bindings and other injector state. This ensures that | |
- // the JIT bindings in the parent injector don't change while we're being built | |
- synchronized (shellBuilder.lock()) { | |
- shells = shellBuilder.build(initializer, bindingProcesor, stopwatch, errors); | |
- stopwatch.resetAndLog("Injector construction"); | |
- | |
- initializeStatically(); | |
- } | |
- | |
- // If we're in the tool stage, stop here. Don't eagerly inject or load anything. | |
- if (stage == Stage.TOOL) { | |
- return new ToolStageInjector(primaryInjector()); | |
- } | |
- | |
- injectDynamically(); | |
- | |
- return primaryInjector(); | |
- } | |
- | |
- /** Initialize and validate everything. */ | |
- private void initializeStatically() { | |
- bindingProcesor.initializeBindings(); | |
- stopwatch.resetAndLog("Binding initialization"); | |
- | |
- for (InjectorShell shell : shells) { | |
- shell.getInjector().index(); | |
- } | |
- stopwatch.resetAndLog("Binding indexing"); | |
- | |
- injectionRequestProcessor.process(shells); | |
- stopwatch.resetAndLog("Collecting injection requests"); | |
- | |
- bindingProcesor.runCreationListeners(); | |
- stopwatch.resetAndLog("Binding validation"); | |
- | |
- injectionRequestProcessor.validate(); | |
- stopwatch.resetAndLog("Static validation"); | |
- | |
- initializer.validateOustandingInjections(errors); | |
- stopwatch.resetAndLog("Instance member validation"); | |
- | |
- new LookupProcessor(errors).process(shells); | |
- for (InjectorShell shell : shells) { | |
- ((DeferredLookups) shell.getInjector().lookups).initialize(errors); | |
- } | |
- stopwatch.resetAndLog("Provider verification"); | |
- | |
- for (InjectorShell shell : shells) { | |
- if (!shell.getElements().isEmpty()) { | |
- throw new AssertionError("Failed to execute " + shell.getElements()); | |
- } | |
- } | |
- | |
- errors.throwCreationExceptionIfErrorsExist(); | |
- } | |
- | |
- /** | |
- * Returns the injector being constructed. This is not necessarily the root injector. | |
- */ | |
- private Injector primaryInjector() { | |
- return shells.get(0).getInjector(); | |
- } | |
- | |
- /** | |
- * Inject everything that can be injected. This method is intentionally not synchronized. If we | |
- * locked while injecting members (ie. running user code), things would deadlock should the user | |
- * code build a just-in-time binding from another thread. | |
- */ | |
- private void injectDynamically() { | |
- injectionRequestProcessor.injectMembers(); | |
- stopwatch.resetAndLog("Static member injection"); | |
- | |
- initializer.injectAll(errors); | |
- stopwatch.resetAndLog("Instance injection"); | |
- errors.throwCreationExceptionIfErrorsExist(); | |
- | |
- for (InjectorShell shell : shells) { | |
- loadEagerSingletons(shell.getInjector(), stage, errors); | |
- } | |
- stopwatch.resetAndLog("Preloading singletons"); | |
- errors.throwCreationExceptionIfErrorsExist(); | |
- } | |
- | |
- /** | |
- * Loads eager singletons, or all singletons if we're in Stage.PRODUCTION. Bindings discovered | |
- * while we're binding these singletons are not be eager. | |
- */ | |
- void loadEagerSingletons(InjectorImpl injector, Stage stage, final Errors errors) { | |
- @SuppressWarnings("unchecked") // casting Collection<Binding> to Collection<BindingImpl> is safe | |
- Set<BindingImpl<?>> candidateBindings = ImmutableSet.copyOf(Iterables.concat( | |
- (Collection) injector.state.getExplicitBindingsThisLevel().values(), | |
- injector.jitBindings.values())); | |
- for (final BindingImpl<?> binding : candidateBindings) { | |
- if (isEagerSingleton(injector, binding, stage)) { | |
- try { | |
- injector.callInContext(new ContextualCallable<Void>() { | |
- Dependency<?> dependency = Dependency.get(binding.getKey()); | |
- public Void call(InternalContext context) { | |
- Dependency previous = context.setDependency(dependency); | |
- Errors errorsForBinding = errors.withSource(dependency); | |
- try { | |
- binding.getInternalFactory().get(errorsForBinding, context, dependency); | |
- } catch (ErrorsException e) { | |
- errorsForBinding.merge(e.getErrors()); | |
- } finally { | |
- context.setDependency(previous); | |
- } | |
- | |
- return null; | |
- } | |
- }); | |
- } catch (ErrorsException e) { | |
- throw new AssertionError(); | |
- } | |
- } | |
- } | |
- } | |
- | |
- private boolean isEagerSingleton(InjectorImpl injector, BindingImpl<?> binding, Stage stage) { | |
- if (binding.getScoping().isEagerSingleton(stage)) { | |
- return true; | |
- } | |
- | |
- // handle a corner case where a child injector links to a binding in a parent injector, and | |
- // that binding is singleton. We won't catch this otherwise because we only iterate the child's | |
- // bindings. | |
- if (binding instanceof LinkedBindingImpl) { | |
- Key<?> linkedBinding = ((LinkedBindingImpl<?>) binding).getLinkedKey(); | |
- return isEagerSingleton(injector, injector.getBinding(linkedBinding), stage); | |
- } | |
- | |
- return false; | |
- } | |
- | |
- /** {@link Injector} exposed to users in {@link Stage#TOOL}. */ | |
- static class ToolStageInjector implements Injector { | |
- private final Injector delegateInjector; | |
- | |
- ToolStageInjector(Injector delegateInjector) { | |
- this.delegateInjector = delegateInjector; | |
- } | |
- public void injectMembers(Object o) { | |
- throw new UnsupportedOperationException( | |
- "Injector.injectMembers(Object) is not supported in Stage.TOOL"); | |
- } | |
- public Map<Key<?>, Binding<?>> getBindings() { | |
- return this.delegateInjector.getBindings(); | |
- } | |
- public Map<Key<?>, Binding<?>> getAllBindings() { | |
- return this.delegateInjector.getAllBindings(); | |
- } | |
- public <T> Binding<T> getBinding(Key<T> key) { | |
- return this.delegateInjector.getBinding(key); | |
- } | |
- public <T> Binding<T> getBinding(Class<T> type) { | |
- return this.delegateInjector.getBinding(type); | |
- } | |
- public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) { | |
- return this.delegateInjector.findBindingsByType(type); | |
- } | |
- public Injector getParent() { | |
- return delegateInjector.getParent(); | |
- } | |
- public Injector createChildInjector(Iterable<? extends Module> modules) { | |
- return delegateInjector.createChildInjector(modules); | |
- } | |
- public Injector createChildInjector(Module... modules) { | |
- return delegateInjector.createChildInjector(modules); | |
- } | |
- public Map<Class<? extends Annotation>, Scope> getScopeBindings() { | |
- return delegateInjector.getScopeBindings(); | |
- } | |
- public <T> Provider<T> getProvider(Key<T> key) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getProvider(Key<T>) is not supported in Stage.TOOL"); | |
- } | |
- public <T> Provider<T> getProvider(Class<T> type) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getProvider(Class<T>) is not supported in Stage.TOOL"); | |
- } | |
- public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getMembersInjector(TypeLiteral<T>) is not supported in Stage.TOOL"); | |
- } | |
- public <T> MembersInjector<T> getMembersInjector(Class<T> type) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getMembersInjector(Class<T>) is not supported in Stage.TOOL"); | |
- } | |
- public <T> T getInstance(Key<T> key) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getInstance(Key<T>) is not supported in Stage.TOOL"); | |
- } | |
- public <T> T getInstance(Class<T> type) { | |
- throw new UnsupportedOperationException( | |
- "Injector.getInstance(Class<T>) is not supported in Stage.TOOL"); | |
- } | |
- } | |
-} | |
Index: src/com/google/inject/internal/ConstructorBindingImpl.java | |
=================================================================== | |
--- src/com/google/inject/internal/ConstructorBindingImpl.java (revision 1113) | |
+++ src/com/google/inject/internal/ConstructorBindingImpl.java (working copy) | |
@@ -50,7 +50,7 @@ | |
public ConstructorBindingImpl(Key<T> key, Object source, Scoping scoping, | |
InjectionPoint constructorInjectionPoint, Set<InjectionPoint> injectionPoints) { | |
super(source, key, scoping); | |
- this.factory = new Factory<T>(); | |
+ this.factory = new Factory<T>(false, key); | |
ConstructionProxy<T> constructionProxy | |
= new DefaultConstructionProxyFactory<T>(constructorInjectionPoint).create(); | |
this.constructorInjectionPoint = constructorInjectionPoint; | |
@@ -60,9 +60,12 @@ | |
/** | |
* @param constructorInjector the constructor to use, or {@code null} to use the default. | |
+ * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should | |
+ * only succeed if retrieved from a linked binding | |
*/ | |
static <T> ConstructorBindingImpl<T> create(InjectorImpl injector, Key<T> key, | |
- InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors) | |
+ InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors, | |
+ boolean failIfNotLinked) | |
throws ErrorsException { | |
int numErrors = errors.size(); | |
Class<? super T> rawType = key.getTypeLiteral().getRawType(); | |
@@ -100,7 +103,7 @@ | |
errors.throwIfNewErrors(numErrors); | |
- Factory<T> factoryFactory = new Factory<T>(); | |
+ Factory<T> factoryFactory = new Factory<T>(failIfNotLinked, key); | |
InternalFactory<? extends T> scopedFactory | |
= Scoping.scope(key, injector, factoryFactory, source, scoping); | |
@@ -168,12 +171,23 @@ | |
} | |
private static class Factory<T> implements InternalFactory<T> { | |
+ private final boolean failIfNotLinked; | |
+ private final Key<?> key; | |
private ConstructorInjector<T> constructorInjector; | |
+ | |
+ Factory(boolean failIfNotLinked, Key<?> key) { | |
+ this.failIfNotLinked = failIfNotLinked; | |
+ this.key = key; | |
+ } | |
@SuppressWarnings("unchecked") | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
checkState(constructorInjector != null, "Constructor not ready"); | |
+ | |
+ if(failIfNotLinked && !linked) { | |
+ throw errors.jitDisabled(key).toException(); | |
+ } | |
// This may not actually be safe because it could return a super type of T (if that's all the | |
// client needs), but it should be OK in practice thanks to the wonders of erasure. | |
Index: src/com/google/inject/internal/FactoryProxy.java | |
=================================================================== | |
--- src/com/google/inject/internal/FactoryProxy.java (revision 1113) | |
+++ src/com/google/inject/internal/FactoryProxy.java (working copy) | |
@@ -21,6 +21,7 @@ | |
/** | |
* A placeholder which enables us to swap in the real factory once the injector is created. | |
+ * Used for a linked binding, so that getting the linked binding returns the link's factory. | |
*/ | |
final class FactoryProxy<T> implements InternalFactory<T>, BindingProcessor.CreationListener { | |
@@ -40,15 +41,15 @@ | |
public void notify(final Errors errors) { | |
try { | |
- targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source)); | |
+ targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source), true); | |
} catch (ErrorsException e) { | |
errors.merge(e.getErrors()); | |
} | |
} | |
- public T get(Errors errors, InternalContext context, Dependency<?> dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked) | |
throws ErrorsException { | |
- return targetFactory.get(errors.withSource(targetKey), context, dependency); | |
+ return targetFactory.get(errors.withSource(targetKey), context, dependency, true); | |
} | |
@Override public String toString() { | |
Index: src/com/google/inject/internal/ConstantFactory.java | |
=================================================================== | |
--- src/com/google/inject/internal/ConstantFactory.java (revision 1113) | |
+++ src/com/google/inject/internal/ConstantFactory.java (working copy) | |
@@ -29,7 +29,7 @@ | |
this.initializable = initializable; | |
} | |
- public T get(Errors errors, InternalContext context, Dependency dependency) | |
+ public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) | |
throws ErrorsException { | |
return initializable.get(errors); | |
} | |
Index: src/com/google/inject/internal/SingleFieldInjector.java | |
=================================================================== | |
--- src/com/google/inject/internal/SingleFieldInjector.java (revision 1113) | |
+++ src/com/google/inject/internal/SingleFieldInjector.java (working copy) | |
@@ -37,7 +37,7 @@ | |
// Ewwwww... | |
field.setAccessible(true); | |
- factory = injector.getInternalFactory(dependency.getKey(), errors); | |
+ factory = injector.getInternalFactory(dependency.getKey(), errors, false); | |
} | |
public InjectionPoint getInjectionPoint() { | |
@@ -49,7 +49,7 @@ | |
Dependency previous = context.setDependency(dependency); | |
try { | |
- Object value = factory.get(errors, context, dependency); | |
+ Object value = factory.get(errors, context, dependency, false); | |
field.set(o, value); | |
} catch (ErrorsException e) { | |
errors.withSource(injectionPoint).merge(e.getErrors()); | |
Index: src/com/google/inject/Guice.java | |
=================================================================== | |
--- src/com/google/inject/Guice.java (revision 1113) | |
+++ src/com/google/inject/Guice.java (working copy) | |
@@ -17,8 +17,10 @@ | |
package com.google.inject; | |
import java.util.Arrays; | |
-import com.google.inject.internal.InjectorBuilder; | |
+import com.google.inject.internal.InjectorBuilderImpl; | |
+ | |
+ | |
/** | |
* The entry point to the Guice framework. Creates {@link Injector}s from | |
* {@link Module}s. | |
@@ -90,9 +92,14 @@ | |
*/ | |
public static Injector createInjector(Stage stage, | |
Iterable<? extends Module> modules) { | |
- return new InjectorBuilder() | |
+ return new InjectorBuilderImpl() | |
.stage(stage) | |
.addModules(modules) | |
.build(); | |
} | |
+ | |
+ /** Creates an {@link InjectorBuilder} which can be used to create an injector. */ | |
+ public static InjectorBuilder createInjectorBuilder() { | |
+ return new InjectorBuilderImpl().stage(Stage.DEVELOPMENT); | |
+ } | |
} | |
Index: src/com/google/inject/Injector.java | |
=================================================================== | |
--- src/com/google/inject/Injector.java (revision 1113) | |
+++ src/com/google/inject/Injector.java (working copy) | |
@@ -20,6 +20,7 @@ | |
import java.util.List; | |
import java.util.Map; | |
+ | |
/** | |
* Builds the graphs of objects that make up your application. The injector tracks the dependencies | |
* for each type and uses bindings to inject them. This is the core of Guice, although you rarely | |
@@ -223,6 +224,11 @@ | |
* @since 2.0 | |
*/ | |
Injector createChildInjector(Module... modules); | |
+ | |
+ /** | |
+ * Creates an InjectorBuilder for a child injector. | |
+ */ | |
+ InjectorBuilder createChildInjectorBuilder(); | |
/** | |
* Returns a map containing all scopes in the injector. The maps keys are scoping annotations | |
Index: src/com/google/inject/Scopes.java | |
=================================================================== | |
--- src/com/google/inject/Scopes.java (revision 1113) | |
+++ src/com/google/inject/Scopes.java (working copy) | |
@@ -16,12 +16,12 @@ | |
package com.google.inject; | |
-import com.google.inject.internal.InjectorBuilder; | |
+import java.lang.annotation.Annotation; | |
+ | |
+import com.google.inject.internal.InjectorBuilderImpl; | |
import com.google.inject.internal.LinkedBindingImpl; | |
import com.google.inject.spi.BindingScopingVisitor; | |
-import java.lang.annotation.Annotation; | |
- | |
/** | |
* Built-in scope implementations. | |
* | |
@@ -56,7 +56,7 @@ | |
* Maybe one of these days we will identify independent graphs of | |
* objects and offer to load them in parallel. | |
*/ | |
- synchronized (InjectorBuilder.class) { | |
+ synchronized (InjectorBuilderImpl.class) { | |
if (instance == null) { | |
T nullableInstance = creator.get(); | |
instance = (nullableInstance != null) ? nullableInstance : NULL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment