---
 .../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 [email protected] (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

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to