Fixes bug with cyclic deps in explicit bindings.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@362 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/BindingBuilderImpl.java b/src/com/google/inject/BindingBuilderImpl.java
index 2b50070..796baa5 100644
--- a/src/com/google/inject/BindingBuilderImpl.java
+++ b/src/com/google/inject/BindingBuilderImpl.java
@@ -285,7 +285,8 @@
Class<T> clazz = (Class<T>) type;
BindingImpl<T> binding = injector.createBindingForInjectableType(
- clazz, scope, source, false);
+ clazz, scope, source);
+ // TODO: Should we clean up the binding left behind in jitBindings?
if (binding == null) {
injector.errorHandler.handle(source,
diff --git a/src/com/google/inject/ErrorMessages.java b/src/com/google/inject/ErrorMessages.java
index f2f5a61..30f6293 100644
--- a/src/com/google/inject/ErrorMessages.java
+++ b/src/com/google/inject/ErrorMessages.java
@@ -138,7 +138,7 @@
+ " types is not supported. Please use a concrete type instead of %s.";
static final String CANNOT_INJECT_INNER_CLASS = "Injecting into inner"
- + " classes is not supported. Please use a static class (top-level or"
+ + " classes is not supported. Please use a 'static' class (top-level or"
+ " nested) instead.";
static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation"
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index 0e9cda8..a8d0ad1 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -464,7 +464,7 @@
*/
<T> BindingImpl<T> createBindingForInjectableType(Class<T> type) {
return createBindingForInjectableType(type, null,
- SourceProviders.defaultSource(), true);
+ SourceProviders.defaultSource());
}
/**
@@ -472,7 +472,7 @@
* a scope on the type if none is specified.
*/
<T> BindingImpl<T> createBindingForInjectableType(Class<T> type,
- Scope scope, Object source, boolean isJit) {
+ Scope scope, Object source) {
// We can't inject abstract classes.
// TODO: Method interceptors could actually enable us to implement
// abstract types. Should we remove this restriction?
@@ -501,12 +501,12 @@
BindingImpl<T> binding
= new ClassBindingImpl<T>(this, key, source, scopedFactory, scope);
- if (isJit) {
- // Put the partially constructed binding in the map a little early. This
- // enables us to handle circular dependencies.
- // Example: FooImpl -> BarImpl -> FooImpl.
- jitBindings.put(key, binding);
- }
+ // Put the partially constructed binding in the map a little early. This
+ // enables us to handle circular dependencies.
+ // Example: FooImpl -> BarImpl -> FooImpl.
+ // Note: We don't need to synchronize on jitBindings during injector
+ // creation.
+ jitBindings.put(key, binding);
try {
lateBoundConstructor.bind(this, type);
@@ -514,16 +514,12 @@
}
catch (RuntimeException e) {
// Clean up state.
- if (isJit) {
- jitBindings.remove(key);
- }
+ jitBindings.remove(key);
throw e;
}
catch (Throwable t) {
// Clean up state.
- if (isJit) {
- jitBindings.remove(key);
- }
+ jitBindings.remove(key);
throw new AssertionError(t);
}
}
@@ -649,7 +645,13 @@
<T> BindingImpl<T> createBindingJustInTime(Key<T> key) {
// Handle cases where T is a Provider<?>.
if (isProvider(key)) {
- return createProviderBindingUnsafely(key);
+ // These casts are safe. We know T extends Provider<X> and that given
+ // Key<Provider<X>>, createProviderBinding() will return
+ // BindingImpl<Provider<X>>.
+ @SuppressWarnings({ "UnnecessaryLocalVariable", "unchecked" })
+ BindingImpl<T> binding
+ = (BindingImpl<T>) createProviderBinding((Key) key);
+ return binding;
}
// Treat primitive types and their wrappers interchangeably.
@@ -686,15 +688,6 @@
return createBindingFromType(clazz);
}
- @SuppressWarnings("unchecked")
- private <T> BindingImpl<T> createProviderBindingUnsafely(Key<T> key) {
- // These casts are safe. We know T extends Provider<X> and that given
- // Key<Provider<X>>, createProviderBinding() will return
- // BindingImpl<Provider<X>>.
- // noinspection unchecked
- return (BindingImpl<T>) createProviderBinding((Key) key);
- }
-
<T> InternalFactory<? extends T> getInternalFactory(Key<T> key) {
BindingImpl<T> binding = getBinding(key);
return binding == null ? null : binding.internalFactory;
diff --git a/test/com/google/inject/BindingTest.java b/test/com/google/inject/BindingTest.java
index f4ec2b7..7a2fcda 100644
--- a/test/com/google/inject/BindingTest.java
+++ b/test/com/google/inject/BindingTest.java
@@ -33,6 +33,18 @@
*/
public class BindingTest extends TestCase {
+ public void testExplicitCyclicDependency() {
+ Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(A.class);
+ bind(B.class);
+ }
+ }).getInstance(A.class);
+ }
+
+ static class A { @Inject B b; }
+ static class B { @Inject A a; }
+
public void testProviderBinding() {
Injector injector = Guice.createInjector();
Binding<Bob> bobBinding = injector.getBinding(Bob.class);