summaryrefslogtreecommitdiffstats
path: root/sangria-lazy
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2015-07-10 22:03:43 -0400
committerTavian Barnes <tavianator@tavianator.com>2015-07-10 22:03:43 -0400
commitbfbf7f869a6e557906f3f4269b52fff57a9c8e4a (patch)
tree4c8c374d9abb26fea0d9c65a39a8e098c6f260d3 /sangria-lazy
parentebbda6f93d4439698727cbf463b20e74a64a03f9 (diff)
parent8c7d863828e0bf4b9045075ff3ccd386993dfbb5 (diff)
downloadsangria-bfbf7f869a6e557906f3f4269b52fff57a9c8e4a.tar.xz
Merge branch 'lazy-fixes'
Diffstat (limited to 'sangria-lazy')
-rw-r--r--sangria-lazy/pom.xml2
-rw-r--r--sangria-lazy/src/main/java/com/tavianator/sangria/lazy/Lazy.java11
-rw-r--r--sangria-lazy/src/main/java/com/tavianator/sangria/lazy/LazyBinder.java17
-rw-r--r--sangria-lazy/src/test/java/com/tavianator/sangria/lazy/LazyTest.java221
4 files changed, 140 insertions, 111 deletions
diff --git a/sangria-lazy/pom.xml b/sangria-lazy/pom.xml
index ba6b122..ed65a96 100644
--- a/sangria-lazy/pom.xml
+++ b/sangria-lazy/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>com.tavianator.sangria</groupId>
<artifactId>sangria</artifactId>
- <version>1.3-SNAPSHOT</version>
+ <version>1.3.1-SNAPSHOT</version>
</parent>
<artifactId>sangria-lazy</artifactId>
diff --git a/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/Lazy.java b/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/Lazy.java
index adf531c..ee42a2f 100644
--- a/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/Lazy.java
+++ b/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/Lazy.java
@@ -56,8 +56,10 @@ import javax.inject.Provider;
* @since 1.2
*/
public final class Lazy<T> {
+ private static final Object SENTINEL = new Object();
+
private final Provider<T> provider;
- private volatile T instance = null;
+ private volatile Object instance = SENTINEL;
@Inject
Lazy(Provider<T> provider) {
@@ -67,15 +69,16 @@ public final class Lazy<T> {
/**
* @return A lazily-produced value of type {@code T}.
*/
+ @SuppressWarnings("unchecked")
public T get() {
// Double-checked locking
- if (instance == null) {
+ if (instance == SENTINEL) {
synchronized (this) {
- if (instance == null) {
+ if (instance == SENTINEL) {
instance = provider.get();
}
}
}
- return instance;
+ return (T) instance;
}
}
diff --git a/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/LazyBinder.java b/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/LazyBinder.java
index 26d3848..baad5da 100644
--- a/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/LazyBinder.java
+++ b/sangria-lazy/src/main/java/com/tavianator/sangria/lazy/LazyBinder.java
@@ -269,5 +269,22 @@ public class LazyBinder {
return visitor.visit(binding);
}
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (!(obj instanceof LazyProvider)) {
+ return false;
+ }
+
+ LazyProvider<?> other = (LazyProvider<?>) obj;
+ return key.equals(other.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
}
}
diff --git a/sangria-lazy/src/test/java/com/tavianator/sangria/lazy/LazyTest.java b/sangria-lazy/src/test/java/com/tavianator/sangria/lazy/LazyTest.java
index 8bea02d..a451a96 100644
--- a/sangria-lazy/src/test/java/com/tavianator/sangria/lazy/LazyTest.java
+++ b/sangria-lazy/src/test/java/com/tavianator/sangria/lazy/LazyTest.java
@@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.*;
import javax.inject.Inject;
import javax.inject.Qualifier;
+import javax.inject.Singleton;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
@@ -30,9 +31,12 @@ import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
+import com.google.inject.ProvidedBy;
+import com.google.inject.Provider;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.Element;
import com.google.inject.spi.Elements;
+import com.google.inject.util.Providers;
import org.junit.Test;
import static com.tavianator.sangria.test.SangriaMatchers.*;
@@ -43,7 +47,7 @@ import static org.junit.Assert.*;
* Tests for {@link Lazy} injection.
*
* @author Tavian Barnes (tavianator@tavianator.com)
- * @version 1.2
+ * @version 1.3
* @since 1.2
*/
public class LazyTest {
@@ -52,157 +56,163 @@ public class LazyTest {
private @interface Simple {
}
+ @ProvidedBy(CountingProvider.class)
private interface Abstract {
}
- private static class Concrete implements Abstract {
- static final ThreadLocal<Integer> INSTANCES = new ThreadLocal<Integer>() {
- @Override
- protected Integer initialValue() {
- return 0;
- }
- };
+ @Singleton
+ private static class CountingProvider implements Provider<Abstract> {
+ int count = 0;
+ private final Provider<Abstract> impl;
@Inject
- Concrete() {
- INSTANCES.set(INSTANCES.get() + 1);
+ CountingProvider() {
+ this.impl = new Provider<Abstract>() {
+ @Override
+ public Abstract get() {
+ return new Abstract() { };
+ }
+ };
+ }
+
+ CountingProvider(Abstract instance) {
+ this.impl = Providers.of(instance);
+ }
+
+ @Override
+ public Abstract get() {
+ ++count;
+ return impl.get();
}
}
- private static class HasConcrete {
- final Lazy<Concrete> lazy;
+ private static class HasLazy {
+ final Lazy<Abstract> lazy;
@Inject
- HasConcrete(Lazy<Concrete> lazy) {
+ HasLazy(Lazy<Abstract> lazy) {
this.lazy = lazy;
}
}
- private static class HasQualifiedAbstract {
- @Inject @Simple Lazy<Abstract> lazy;
+ private static class HasSimpleLazy extends HasLazy {
+ @Inject
+ HasSimpleLazy(@Simple Lazy<Abstract> lazy) {
+ super(lazy);
+ }
}
- @Test
- public void testJustInTime() {
- testHasConcrete(Guice.createInjector());
- }
+ private void test(Injector injector, Class<? extends HasLazy> type) {
+ CountingProvider provider = injector.getInstance(CountingProvider.class);
+ HasLazy hasLazy = injector.getInstance(type);
+ assertThat(provider.count, equalTo(0));
- @Test
- public void testExplicitBindings() {
- testHasConcrete(Guice.createInjector(new AbstractModule() {
- @Override
- protected void configure() {
- binder().requireExplicitBindings();
+ Abstract a = hasLazy.lazy.get();
+ assertThat(provider.count, equalTo(1));
- bind(HasConcrete.class);
+ assertThat(hasLazy.lazy.get(), sameInstance(a));
+ assertThat(provider.count, equalTo(1));
- bind(Concrete.class);
- LazyBinder.create(binder())
- .bind(Concrete.class);
- }
- }));
+ hasLazy = injector.getInstance(type);
+ assertThat(provider.count, equalTo(1));
+
+ a = hasLazy.lazy.get();
+ assertThat(provider.count, equalTo(2));
+
+ assertThat(hasLazy.lazy.get(), sameInstance(a));
+ assertThat(provider.count, equalTo(2));
}
@Test
- public void testBestPractices() {
- Module module = new AbstractModule() {
- @Override
- protected void configure() {
- bind(HasConcrete.class);
-
- bind(Concrete.class);
- LazyBinder.create(binder())
- .bind(Concrete.class);
- }
- };
- assertThat(module, is(atomic()));
- assertThat(module, followsBestPractices());
+ public void testJustInTime() {
+ test(Guice.createInjector(), HasLazy.class);
}
- private void testHasConcrete(Injector injector) {
- int before = Concrete.INSTANCES.get();
+ private static final Module EXPLICIT_MODULE = new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Abstract.class)
+ .toProvider(CountingProvider.class);
- HasConcrete hasConcrete = injector.getInstance(HasConcrete.class);
- assertThat(Concrete.INSTANCES.get(), equalTo(before));
+ LazyBinder.create(binder())
+ .bind(Abstract.class);
- Concrete instance = hasConcrete.lazy.get();
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
+ bind(HasLazy.class);
+ }
+ };
- Concrete instance2 = hasConcrete.lazy.get();
- assertThat(instance2, sameInstance(instance));
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
+ @Test
+ public void testExplicitBindings() {
+ test(Guice.createInjector(EXPLICIT_MODULE), HasLazy.class);
+ }
- HasConcrete hasConcrete2 = injector.getInstance(HasConcrete.class);
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
+ private static final Module BIND_SEPARATELY_MODULE = new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Abstract.class)
+ .annotatedWith(Simple.class)
+ .toProvider(CountingProvider.class);
- Concrete instance3 = hasConcrete2.lazy.get();
- assertThat(instance3, not(sameInstance(instance)));
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 2));
- }
+ LazyBinder.create(binder())
+ .bind(Abstract.class)
+ .annotatedWith(Simple.class);
+
+ bind(HasSimpleLazy.class);
+ }
+ };
@Test
public void testBindSeparately() {
- testQualifiedAbstract(Guice.createInjector(new AbstractModule() {
- @Override
- protected void configure() {
- bind(Abstract.class)
- .annotatedWith(Simple.class)
- .to(Concrete.class);
-
- LazyBinder.create(binder())
- .bind(Abstract.class)
- .annotatedWith(Simple.class);
- }
- }));
+ test(Guice.createInjector(BIND_SEPARATELY_MODULE), HasSimpleLazy.class);
}
+ private static final Module BIND_TOGETHER_MODULE = new AbstractModule() {
+ @Override
+ protected void configure() {
+ LazyBinder.create(binder())
+ .bind(Abstract.class)
+ .annotatedWith(Simple.class)
+ .toProvider(CountingProvider.class);
+
+ bind(HasSimpleLazy.class);
+ }
+ };
+
@Test
public void testBindTogether() {
- testQualifiedAbstract(Guice.createInjector(new AbstractModule() {
+ test(Guice.createInjector(BIND_TOGETHER_MODULE), HasSimpleLazy.class);
+ }
+
+ @Test
+ public void testBestPractices() {
+ Module module = new AbstractModule() {
@Override
protected void configure() {
- LazyBinder.create(binder())
- .bind(Abstract.class)
- .annotatedWith(Simple.class)
- .to(Concrete.class);
+ install(EXPLICIT_MODULE);
+ install(BIND_SEPARATELY_MODULE);
+ install(BIND_TOGETHER_MODULE);
}
- }));
- }
-
- private void testQualifiedAbstract(Injector injector) {
- int before = Concrete.INSTANCES.get();
-
- HasQualifiedAbstract hasQualifiedAbstract = injector.getInstance(HasQualifiedAbstract.class);
- assertThat(Concrete.INSTANCES.get(), equalTo(before));
-
- Abstract instance = hasQualifiedAbstract.lazy.get();
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
-
- Abstract instance2 = hasQualifiedAbstract.lazy.get();
- assertThat(instance2, sameInstance(instance2));
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
-
- HasQualifiedAbstract hasQualifiedAbstract2 = injector.getInstance(HasQualifiedAbstract.class);
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 1));
+ };
- Abstract instance3 = hasQualifiedAbstract2.lazy.get();
- assertThat(instance3, not(sameInstance(instance)));
- assertThat(Concrete.INSTANCES.get(), equalTo(before + 2));
+ assertThat(module, is(atomic()));
+ assertThat(module, followsBestPractices());
}
- @Test(expected = CreationException.class)
- public void testMissingBinding() {
- Guice.createInjector(new AbstractModule() {
+ @Test
+ public void testNull() {
+ Module module = new AbstractModule() {
@Override
protected void configure() {
- LazyBinder.create(binder())
- .bind(Abstract.class);
+ bind(CountingProvider.class)
+ .toInstance(new CountingProvider(null));
}
- });
+ };
+
+ test(Guice.createInjector(module), HasLazy.class);
}
@Test(expected = CreationException.class)
- public void testMissingQualifiedBinding() {
+ public void testMissingBinding() {
Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
@@ -239,7 +249,7 @@ public class LazyTest {
LazyBinder.create(binder())
.bind(Abstract.class)
.annotatedWith(Simple.class)
- .to(Concrete.class);
+ .toProvider(CountingProvider.class);
}
};
@@ -258,6 +268,5 @@ public class LazyTest {
Injector injector = Guice.createInjector(Elements.getModule(elements));
assertThat(visit(injector.getBinding(new Key<Lazy<Abstract>>(Simple.class) { })), is(true));
assertThat(visit(injector.getBinding(new Key<Abstract>(Simple.class) { })), is(false));
- assertThat(visit(injector.getBinding(new Key<Concrete>() { })), is(false));
}
}