Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #54 from square/jwilson/getinstance

Implement ObjectGraph.getInstance().
  • Loading branch information...
commit 9a99cd0b9ae61530787fa6a39a61fd9677deb1dd 2 parents e7d79d0 + 4e33f84
@cgruber cgruber authored
View
5 README.md
@@ -102,7 +102,7 @@ The `@Inject` and `@Provides`-annotated classes form a graph of objects, linked
ObjectGraph objectGraph = ObjectGraph.get(new DripCoffeeModule());
```
-In order to put the graph to use we need to create an **entry point**. This is usually the main class that starts the application. In this example, the `CoffeeApp` class serves as the entry point. We construct an instance of this type and then ask the object graph to inject its fields.
+In order to put the graph to use we need to create an **entry point**. This is usually the main class that starts the application. In this example, the `CoffeeApp` class serves as the entry point. We ask the graph to provide an injected instance of this type:
```java
class CoffeeApp implements Runnable {
@@ -114,8 +114,7 @@ class CoffeeApp implements Runnable {
public static void main(String[] args) {
ObjectGraph objectGraph = ObjectGraph.get(new DripCoffeeModule());
- CoffeeApp coffeeApp = new CoffeeApp();
- objectGraph.inject(coffeeApp);
+ CoffeeApp coffeeApp = objectGraph.getInstance(CoffeeApp.class);
...
}
}
View
40 core/src/main/java/dagger/ObjectGraph.java
@@ -105,8 +105,7 @@ public static ObjectGraph get(Object... modules) {
linker.installBindings(baseBindings);
linker.installBindings(overrideBindings);
- ObjectGraph result = new ObjectGraph(linker, staticInjections, entryPoints);
- return result;
+ return new ObjectGraph(linker, staticInjections, entryPoints);
}
/**
@@ -205,18 +204,43 @@ public void injectStatics() {
}
/**
+ * Returns an instance of {@code type}.
+ *
+ * @throws IllegalArgumentException if {@code type} is not one of this object
+ * graph's entry point types.
+ */
+ public <T> T getInstance(Class<T> type) {
+ String key = Keys.get(type);
+ @SuppressWarnings("unchecked") // The linker matches keys to bindings by their type.
+ Binding<T> binding = (Binding<T>) getEntryPointBinding(key, key);
+ return binding.get();
+ }
+
+ /**
* Injects the members of {@code instance}, including injectable members
* inherited from its supertypes.
*
* @throws IllegalArgumentException if the runtime type of {@code instance} is
- * not the object graph's type or one of its entry point types.
+ * not one of this object graph's entry point types.
*/
- @SuppressWarnings("unchecked") // the linker matches keys to bindings by their type
public void inject(Object instance) {
- String key = Keys.getMembersKey(instance.getClass());
- Class<?> moduleClass = entryPoints.get(key);
+ String entryPointKey = Keys.get(instance.getClass());
+ String membersKey = Keys.getMembersKey(instance.getClass());
+ @SuppressWarnings("unchecked") // The linker matches keys to bindings by their type.
+ Binding<Object> binding = (Binding<Object>) getEntryPointBinding(entryPointKey, membersKey);
+ binding.injectMembers(instance);
+ }
+
+ /**
+ * @param entryPointKey the key used to store the entry point. This is always
+ * a regular (provider) key.
+ * @param key the key to use when retrieving the binding. This may be a
+ * regular (provider) key or a members key.
+ */
+ private Binding<?> getEntryPointBinding(String entryPointKey, String key) {
+ Class<?> moduleClass = entryPoints.get(entryPointKey);
if (moduleClass == null) {
- throw new IllegalArgumentException("No entry point for " + instance.getClass().getName()
+ throw new IllegalArgumentException("No entry point for " + entryPointKey
+ ". You must explicitly add an entry point to one of your modules.");
}
Binding<?> binding = linker.requestBinding(key, moduleClass);
@@ -224,6 +248,6 @@ public void inject(Object instance) {
linker.linkRequested();
binding = linker.requestBinding(key, moduleClass);
}
- ((Binding<Object>) binding).injectMembers(instance);
+ return binding;
}
}
View
10 core/src/main/java/dagger/internal/ModuleAdapter.java
@@ -17,9 +17,9 @@
package dagger.internal;
-import dagger.OneOf;
import dagger.Module;
import dagger.ObjectGraph;
+import dagger.OneOf;
import dagger.Provides;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@@ -96,8 +96,8 @@ public T getModule() {
@SuppressWarnings("deprecation") // explicitly handles deprecated case
ReflectiveModuleAdapter(Class<?> moduleClass, Module annotation) {
- super(toMemberKeys(
- annotation.entryPoints()),
+ super(
+ toKeys(annotation.entryPoints()),
annotation.staticInjections(),
annotation.overrides(),
annotation.includes(),
@@ -105,10 +105,10 @@ public T getModule() {
this.moduleClass = moduleClass;
}
- private static String[] toMemberKeys(Class<?>[] entryPoints) {
+ private static String[] toKeys(Class<?>[] entryPoints) {
String[] result = new String[entryPoints.length];
for (int i = 0; i < entryPoints.length; i++) {
- result[i] = Keys.getMembersKey(entryPoints[i]);
+ result[i] = Keys.get(entryPoints[i]);
}
return result;
}
View
2  core/src/main/java/dagger/internal/codegen/ProvidesProcessor.java
@@ -163,7 +163,7 @@ private void writeModuleAdapter(TypeElement type, List<ExecutableElement> provid
StringBuilder entryPointsField = new StringBuilder().append("{ ");
for (Object entryPoint : entryPoints) {
TypeMirror typeMirror = (TypeMirror) entryPoint;
- String key = GeneratorKeys.rawMembersKey(typeMirror);
+ String key = GeneratorKeys.get(typeMirror);
entryPointsField.append(JavaWriter.stringLiteral(key)).append(", ");
}
entryPointsField.append("}");
View
85 core/src/test/java/dagger/InjectionTest.java
@@ -20,6 +20,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.RandomAccess;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
@@ -27,6 +28,7 @@
import org.junit.Test;
import static org.fest.assertions.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@SuppressWarnings("unused")
@@ -508,4 +510,87 @@
ObjectGraph.get(new TestModule());
}
+
+ @Test public void getInstance() {
+ final AtomicInteger next = new AtomicInteger(0);
+
+ @Module(entryPoints = Integer.class)
+ class TestModule {
+ @Provides Integer provideInteger() {
+ return next.getAndIncrement();
+ }
+ }
+
+ ObjectGraph graph = ObjectGraph.get(new TestModule());
+ assertEquals(0, (int) graph.getInstance(Integer.class));
+ assertEquals(1, (int) graph.getInstance(Integer.class));
+ }
+
+ @Test public void getInstanceRequiresEntryPoint() {
+ @Module
+ class TestModule {
+ @Provides Integer provideInteger() {
+ throw new AssertionError();
+ }
+ }
+
+ ObjectGraph graph = ObjectGraph.get(new TestModule());
+ try {
+ graph.getInstance(Integer.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test public void getInstanceOfPrimitive() {
+ @Module(entryPoints = int.class)
+ class TestModule {
+ @Provides int provideInt() {
+ return 1;
+ }
+ }
+
+ ObjectGraph graph = ObjectGraph.get(new TestModule());
+ assertEquals(1, (int) graph.getInstance(int.class));
+ }
+
+ @Test public void getInstanceOfArray() {
+ @Module(entryPoints = int[].class)
+ class TestModule {
+ @Provides int[] provideIntArray() {
+ return new int[] { 1, 2, 3 };
+ }
+ }
+
+ ObjectGraph graph = ObjectGraph.get(new TestModule());
+ assertEquals("[1, 2, 3]", Arrays.toString(graph.getInstance(int[].class)));
+ }
+
+ @Test public void getInstanceAndInjectMembersUseDifferentKeys() {
+ class BoundTwoWays {
+ @Inject String s;
+ }
+
+ @Module(entryPoints = BoundTwoWays.class)
+ class TestModule {
+ @Provides
+ BoundTwoWays provideBoundTwoWays() {
+ BoundTwoWays result = new BoundTwoWays();
+ result.s = "Pepsi";
+ return result;
+ }
+
+ @Provides String provideString() {
+ return "Coke";
+ }
+ }
+
+ ObjectGraph graph = ObjectGraph.get(new TestModule());
+ BoundTwoWays provided = graph.getInstance(BoundTwoWays.class);
+ assertEquals("Pepsi", provided.s);
+
+ BoundTwoWays membersInjected = new BoundTwoWays();
+ graph.inject(membersInjected);
+ assertEquals("Coke", membersInjected.s);
+ }
}
View
8 core/src/test/java/dagger/MembersInjectorTest.java
@@ -92,7 +92,7 @@
ObjectGraph graph = ObjectGraph.get(new TestModule());
try {
- graph.inject(new TestEntryPoint());
+ graph.getInstance(TestEntryPoint.class);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -109,7 +109,7 @@
ObjectGraph graph = ObjectGraph.get(new TestModule());
try {
- graph.inject(new TestEntryPoint());
+ graph.getInstance(TestEntryPoint.class);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -126,7 +126,7 @@
ObjectGraph graph = ObjectGraph.get(new TestModule());
try {
- graph.inject(new TestEntryPoint());
+ graph.getInstance(TestEntryPoint.class);
fail();
} catch (IllegalArgumentException expected) {
}
@@ -175,7 +175,7 @@
ObjectGraph graph = ObjectGraph.get(new TestModule());
try {
- graph.inject(new TestEntryPoint());
+ graph.getInstance(TestEntryPoint.class);
fail();
} catch (IllegalArgumentException expected) {
}
View
10 core/src/test/java/dagger/ModuleIncludesTest.java
@@ -40,8 +40,7 @@
}
ObjectGraph objectGraph = ObjectGraph.get(new TestModule());
- TestEntryPoint entryPoint = new TestEntryPoint();
- objectGraph.inject(entryPoint);
+ TestEntryPoint entryPoint = objectGraph.getInstance(TestEntryPoint.class);
assertThat(entryPoint.s).isEqualTo("injected");
}
@@ -156,11 +155,4 @@
objectGraph.inject(entryPoint);
assertThat(entryPoint.s).isEqualTo("a");
}
-
- private <T> T injectWithModule(T ep, Object ... modules) {
- // TODO(cgruber): Make og.inject(foo) return foo properly.
- ObjectGraph og = ObjectGraph.get(modules);
- og.inject(ep);
- return ep;
- }
}
View
3  example/src/main/java/coffee/CoffeeApp.java
@@ -12,8 +12,7 @@
public static void main(String[] args) {
ObjectGraph objectGraph = ObjectGraph.get(new DripCoffeeModule());
- CoffeeApp coffeeApp = new CoffeeApp();
- objectGraph.inject(coffeeApp);
+ CoffeeApp coffeeApp = objectGraph.getInstance(CoffeeApp.class);
coffeeApp.run();
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.