Created
July 7, 2014 19:14
-
-
Save gissuebot/65062e1df7507ef31b3c to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 779, comment 0
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
From 04039d5d84d4cf162c2657564caec161a6ae0c9c Mon Sep 17 00:00:00 2001 | |
From: Tavian Barnes <tavianator@tavianator.com> | |
Date: Wed, 6 Nov 2013 13:44:13 -0500 | |
Subject: [PATCH 1/3] De-duplicate ProvisionListeners. | |
If a binding has two equivalent ProvisionListeners, only fire one of them. | |
--- | |
.../inject/internal/ProvisionListenerStackCallback.java | 9 ++++++--- | |
core/test/com/google/inject/ProvisionListenerTest.java | 13 +++++++++++++ | |
2 files changed, 19 insertions(+), 3 deletions(-) | |
diff --git a/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java b/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java | |
index a99c513..45347f0 100644 | |
--- a/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java | |
+++ b/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java | |
@@ -16,14 +16,16 @@ | |
package com.google.inject.internal; | |
+import java.util.List; | |
+import java.util.Set; | |
+ | |
import com.google.common.collect.ImmutableList; | |
+import com.google.common.collect.Sets; | |
import com.google.inject.Binding; | |
import com.google.inject.ProvisionException; | |
import com.google.inject.spi.DependencyAndSource; | |
import com.google.inject.spi.ProvisionListener; | |
-import java.util.List; | |
- | |
/** | |
* Intercepts provisions with a stack of listeners. | |
* | |
@@ -49,7 +51,8 @@ final class ProvisionListenerStackCallback<T> { | |
if (listeners.isEmpty()) { | |
this.listeners = EMPTY_LISTENER; | |
} else { | |
- this.listeners = listeners.toArray(new ProvisionListener[listeners.size()]); | |
+ Set<ProvisionListener> deDuplicated = Sets.newLinkedHashSet(listeners); | |
+ this.listeners = deDuplicated.toArray(new ProvisionListener[deDuplicated.size()]); | |
} | |
} | |
diff --git a/core/test/com/google/inject/ProvisionListenerTest.java b/core/test/com/google/inject/ProvisionListenerTest.java | |
index 478949f..54a11fa 100644 | |
--- a/core/test/com/google/inject/ProvisionListenerTest.java | |
+++ b/core/test/com/google/inject/ProvisionListenerTest.java | |
@@ -694,4 +694,17 @@ public class ProvisionListenerTest extends TestCase { | |
this.x = xProvider.get(); | |
} | |
} | |
+ | |
+ public void testDeDuplicateProvisionListeners() { | |
+ final Counter counter = new Counter(); | |
+ Injector injector = Guice.createInjector(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bindListener(Matchers.any(), counter); | |
+ bindListener(Matchers.any(), counter); | |
+ } | |
+ }); | |
+ injector.getInstance(Many.class); | |
+ assertEquals("ProvisionListener not de-duplicated", 1, counter.count); | |
+ } | |
} | |
-- | |
1.8.4.2 | |
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
From 9aca6281939c9b9036d1e3cd8f45f11fdd1dc69a Mon Sep 17 00:00:00 2001 | |
From: Tavian Barnes <tavianator@tavianator.com> | |
Date: Wed, 6 Nov 2013 15:09:38 -0500 | |
Subject: [PATCH 2/3] De-duplicate TypeListeners, MembersInjectors, and | |
InjectionListeners. | |
--- | |
.../inject/internal/MembersInjectorImpl.java | 5 ++- | |
.../inject/internal/MembersInjectorStore.java | 21 ++++++---- | |
core/test/com/google/inject/TypeListenerTest.java | 48 ++++++++++++++++++++++ | |
3 files changed, 64 insertions(+), 10 deletions(-) | |
diff --git a/core/src/com/google/inject/internal/MembersInjectorImpl.java b/core/src/com/google/inject/internal/MembersInjectorImpl.java | |
index ba32d28..42ab050 100644 | |
--- a/core/src/com/google/inject/internal/MembersInjectorImpl.java | |
+++ b/core/src/com/google/inject/internal/MembersInjectorImpl.java | |
@@ -45,8 +45,9 @@ final class MembersInjectorImpl<T> implements MembersInjector<T> { | |
this.injector = injector; | |
this.typeLiteral = typeLiteral; | |
this.memberInjectors = memberInjectors; | |
- this.userMembersInjectors = encounter.getMembersInjectors(); | |
- this.injectionListeners = encounter.getInjectionListeners(); | |
+ // De-duplicate members injectors and listeners | |
+ this.userMembersInjectors = ImmutableSet.copyOf(encounter.getMembersInjectors()).asList(); | |
+ this.injectionListeners = ImmutableSet.copyOf(encounter.getInjectionListeners()).asList(); | |
/*if[AOP]*/ | |
this.addedAspects = encounter.getAspects(); | |
/*end[AOP]*/ | |
diff --git a/core/src/com/google/inject/internal/MembersInjectorStore.java b/core/src/com/google/inject/internal/MembersInjectorStore.java | |
index 7604d4c..37a7f1b 100644 | |
--- a/core/src/com/google/inject/internal/MembersInjectorStore.java | |
+++ b/core/src/com/google/inject/internal/MembersInjectorStore.java | |
@@ -16,17 +16,19 @@ | |
package com.google.inject.internal; | |
+import java.lang.reflect.Field; | |
+import java.util.List; | |
+import java.util.Set; | |
+ | |
import com.google.common.collect.ImmutableList; | |
import com.google.common.collect.Lists; | |
+import com.google.common.collect.Sets; | |
import com.google.inject.ConfigurationException; | |
import com.google.inject.TypeLiteral; | |
import com.google.inject.spi.InjectionPoint; | |
+import com.google.inject.spi.TypeListener; | |
import com.google.inject.spi.TypeListenerBinding; | |
-import java.lang.reflect.Field; | |
-import java.util.List; | |
-import java.util.Set; | |
- | |
/** | |
* Members injectors by type. | |
* | |
@@ -97,12 +99,15 @@ final class MembersInjectorStore { | |
errors.throwIfNewErrors(numErrorsBefore); | |
EncounterImpl<T> encounter = new EncounterImpl<T>(errors, injector.lookups); | |
- for (TypeListenerBinding typeListener : typeListenerBindings) { | |
- if (typeListener.getTypeMatcher().matches(type)) { | |
+ Set<TypeListener> typeListeners = Sets.newHashSet(); | |
+ for (TypeListenerBinding binding : typeListenerBindings) { | |
+ TypeListener typeListener = binding.getListener(); | |
+ if (!typeListeners.contains(typeListener) && binding.getTypeMatcher().matches(type)) { | |
+ typeListeners.add(typeListener); | |
try { | |
- typeListener.getListener().hear(type, encounter); | |
+ typeListener.hear(type, encounter); | |
} catch (RuntimeException e) { | |
- errors.errorNotifyingTypeListener(typeListener, type, e); | |
+ errors.errorNotifyingTypeListener(binding, type, e); | |
} | |
} | |
} | |
diff --git a/core/test/com/google/inject/TypeListenerTest.java b/core/test/com/google/inject/TypeListenerTest.java | |
index e4b5f63..a1468dd 100644 | |
--- a/core/test/com/google/inject/TypeListenerTest.java | |
+++ b/core/test/com/google/inject/TypeListenerTest.java | |
@@ -38,6 +38,8 @@ import java.util.List; | |
import java.util.concurrent.atomic.AtomicInteger; | |
import java.util.concurrent.atomic.AtomicReference; | |
+import org.junit.experimental.runners.Enclosed; | |
+ | |
/** | |
* @author jessewilson@google.com (Jesse Wilson) | |
*/ | |
@@ -630,6 +632,52 @@ public class TypeListenerTest extends TestCase { | |
} | |
} | |
+ private static class CountingMembersInjector implements MembersInjector<D> { | |
+ @Override | |
+ public void injectMembers(D instance) { | |
+ ++instance.userInjected; | |
+ } | |
+ } | |
+ | |
+ private static class CountingInjectionListener implements InjectionListener<D> { | |
+ @Override | |
+ public void afterInjection(D injectee) { | |
+ ++injectee.listenersNotified; | |
+ } | |
+ } | |
+ | |
+ private static class DuplicatingTypeListener implements TypeListener { | |
+ int count = 0; | |
+ | |
+ @SuppressWarnings({ "rawtypes", "unchecked" }) | |
+ @Override | |
+ public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) { | |
+ ++count; | |
+ | |
+ MembersInjector membersInjector = new CountingMembersInjector(); | |
+ encounter.register(membersInjector); | |
+ encounter.register(membersInjector); | |
+ | |
+ InjectionListener injectionListener = new CountingInjectionListener(); | |
+ encounter.register(injectionListener); | |
+ encounter.register(injectionListener); | |
+ } | |
+ } | |
+ | |
+ public void testDeDuplicateTypeListeners() { | |
+ final DuplicatingTypeListener typeListener = new DuplicatingTypeListener(); | |
+ Injector injector = Guice.createInjector(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ bindListener(any(), typeListener); | |
+ bindListener(only(new TypeLiteral<D>() { }), typeListener); | |
+ } | |
+ }); | |
+ D d = injector.getInstance(D.class); | |
+ d.assertAllCounts(1); | |
+ assertEquals(1, typeListener.count); | |
+ } | |
+ | |
// TODO: recursively accessing a lookup should fail | |
static class A { | |
-- | |
1.8.4.2 | |
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
From 89c80b9285f05fcd80b9c130c854cfaf3827ddbe Mon Sep 17 00:00:00 2001 | |
From: Tavian Barnes <tavianator@tavianator.com> | |
Date: Wed, 6 Nov 2013 15:39:13 -0500 | |
Subject: [PATCH 3/3] De-duplicate MethodInterceptors. | |
--- | |
core/src/com/google/inject/internal/ProxyFactory.java | 6 ++++-- | |
core/test/com/google/inject/MethodInterceptionTest.java | 14 ++++++++++++++ | |
2 files changed, 18 insertions(+), 2 deletions(-) | |
diff --git a/core/src/com/google/inject/internal/ProxyFactory.java b/core/src/com/google/inject/internal/ProxyFactory.java | |
index 0b39f76..07d0045 100644 | |
--- a/core/src/com/google/inject/internal/ProxyFactory.java | |
+++ b/core/src/com/google/inject/internal/ProxyFactory.java | |
@@ -20,6 +20,7 @@ import static com.google.inject.internal.BytecodeGen.newFastClass; | |
import com.google.common.collect.ImmutableList; | |
import com.google.common.collect.ImmutableMap; | |
+import com.google.common.collect.ImmutableSet; | |
import com.google.common.collect.Lists; | |
import com.google.common.collect.Maps; | |
import com.google.inject.spi.InjectionPoint; | |
@@ -135,8 +136,9 @@ final class ProxyFactory<T> implements ConstructionProxyFactory<T> { | |
interceptorsMapBuilder = ImmutableMap.builder(); | |
} | |
- interceptorsMapBuilder.put(pair.method, ImmutableList.copyOf(pair.interceptors)); | |
- callbacks[i] = new InterceptorStackCallback(pair.method, pair.interceptors); | |
+ ImmutableList<MethodInterceptor> deDuplicated = ImmutableSet.copyOf(pair.interceptors).asList(); | |
+ interceptorsMapBuilder.put(pair.method, deDuplicated); | |
+ callbacks[i] = new InterceptorStackCallback(pair.method, deDuplicated); | |
} | |
interceptors = interceptorsMapBuilder != null | |
diff --git a/core/test/com/google/inject/MethodInterceptionTest.java b/core/test/com/google/inject/MethodInterceptionTest.java | |
index 6fe8b4e..e3bb97e 100644 | |
--- a/core/test/com/google/inject/MethodInterceptionTest.java | |
+++ b/core/test/com/google/inject/MethodInterceptionTest.java | |
@@ -313,4 +313,18 @@ public class MethodInterceptionTest extends TestCase { | |
} | |
} | |
+ public void testDeDuplicateInterceptors() throws Exception { | |
+ Injector injector = Guice.createInjector(new AbstractModule() { | |
+ @Override | |
+ protected void configure() { | |
+ CountingInterceptor interceptor = new CountingInterceptor(); | |
+ bindInterceptor(Matchers.any(), Matchers.any(), interceptor); | |
+ bindInterceptor(Matchers.any(), Matchers.any(), interceptor); | |
+ } | |
+ }); | |
+ | |
+ Interceptable interceptable = injector.getInstance(Interceptable.class); | |
+ interceptable.foo(); | |
+ assertEquals(1, count.get()); | |
+ } | |
} | |
-- | |
1.8.4.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment