Revision: d51292d5a4a7
Author: Sam Berlin <[email protected]>
Date: Sun Feb 26 18:23:19 2012
Log: Change ProvisionListener to expose Binding instead of Key, and
change bindListener to use a Matcher for Binding instead of Key. This is a
backwards incompatible change, but we haven't released yet, so it's worth
doing.
Revision created by MOE tool push_codebase.
MOE_MIGRATION=4269
http://code.google.com/p/google-guice/source/detail?r=d51292d5a4a7
Modified:
/core/src/com/google/inject/AbstractModule.java
/core/src/com/google/inject/Binder.java
/core/src/com/google/inject/internal/BindingProcessor.java
/core/src/com/google/inject/internal/BoundProviderFactory.java
/core/src/com/google/inject/internal/ConstructorBindingImpl.java
/core/src/com/google/inject/internal/ConstructorInjector.java
/core/src/com/google/inject/internal/InjectorImpl.java
/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
/core/src/com/google/inject/internal/ProvidedByInternalFactory.java
/core/src/com/google/inject/internal/ProviderInternalFactory.java
/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
/core/src/com/google/inject/spi/DependencyAndSource.java
/core/src/com/google/inject/spi/Elements.java
/core/src/com/google/inject/spi/ProvisionListener.java
/core/src/com/google/inject/spi/ProvisionListenerBinding.java
/core/test/com/google/inject/ProvisionListenerTest.java
=======================================
--- /core/src/com/google/inject/AbstractModule.java Tue Oct 18 13:43:18 2011
+++ /core/src/com/google/inject/AbstractModule.java Sun Feb 26 18:23:19 2012
@@ -256,11 +256,11 @@
}
/**
- * @see Binder#bindListener(Matcher, ProvisionListener)
+ * @see Binder#bindListener(Matcher, ProvisionListener...)
* @since 4.0
*/
- protected void bindListener(Matcher<? super Key<?>> keyMatcher,
+ protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
ProvisionListener... listener) {
- binder().bindListener(keyMatcher, listener);
+ binder().bindListener(bindingMatcher, listener);
}
}
=======================================
--- /core/src/com/google/inject/Binder.java Thu Jul 7 17:34:16 2011
+++ /core/src/com/google/inject/Binder.java Sun Feb 26 18:23:19 2012
@@ -383,12 +383,12 @@
* through Providers) can also be notified through TypeListeners
registered in
* {@link #bindListener}.
*
- * @param keyMatcher that matches keys of provisioned objects the
listener
+ * @param bindingMatcher that matches bindings of provisioned objects
the listener
* should be notified of
- * @param listeners for provisioned objects matched by keyMatcher *
+ * @param listeners for provisioned objects matched by bindingMatcher
* @since 4.0
*/
- void bindListener(Matcher<? super Key<?>> keyMatcher,
ProvisionListener... listeners);
+ void bindListener(Matcher<? super Binding<?>> bindingMatcher,
ProvisionListener... listeners);
/**
* Returns a binder that uses {@code source} as the reference location
for
=======================================
--- /core/src/com/google/inject/internal/BindingProcessor.java Thu Jul 7
17:34:16 2011
+++ /core/src/com/google/inject/internal/BindingProcessor.java Sun Feb 26
18:23:19 2012
@@ -67,6 +67,7 @@
}
return command.acceptTargetVisitor(new Processor<T,
Boolean>((BindingImpl<T>)command) {
+ @Override
public Boolean visit(ConstructorBinding<? extends T> binding) {
prepareBinding();
try {
@@ -81,6 +82,7 @@
return true;
}
+ @Override
public Boolean visit(InstanceBinding<? extends T> binding) {
prepareBinding();
Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
@@ -95,15 +97,18 @@
return true;
}
+ @Override
public Boolean visit(ProviderInstanceBinding<? extends T> binding) {
prepareBinding();
Provider<? extends T> provider = binding.getProviderInstance();
Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
Initializable<Provider<? extends T>> initializable = initializer
.<Provider<? extends T>>requestInjection(injector, provider,
null, source, injectionPoints);
+ // always visited with Binding<T>
+ @SuppressWarnings("unchecked")
InternalFactory<T> factory = new
InternalFactoryToInitializableAdapter<T>(
initializable,
source, !injector.options.disableCircularProxies,
- injector.provisionListenerStore.get(key));
+
injector.provisionListenerStore.get((ProviderInstanceBinding<T>)binding));
InternalFactory<? extends T> scopedFactory
= Scoping.scope(key, injector, factory, source, scoping);
putBinding(new ProviderInstanceBindingImpl<T>(injector, key,
source, scopedFactory, scoping,
@@ -111,12 +116,15 @@
return true;
}
+ @Override
public Boolean visit(ProviderKeyBinding<? extends T> binding) {
prepareBinding();
Key<? extends javax.inject.Provider<? extends T>> providerKey =
binding.getProviderKey();
+ // always visited with Binding<T>
+ @SuppressWarnings("unchecked")
BoundProviderFactory<T> boundProviderFactory = new
BoundProviderFactory<T>(
injector, providerKey,
source, !injector.options.disableCircularProxies,
- injector.provisionListenerStore.get(key));
+
injector.provisionListenerStore.get((ProviderKeyBinding<T>)binding));
bindingData.addCreationListener(boundProviderFactory);
InternalFactory<? extends T> scopedFactory = Scoping.scope(
key, injector, (InternalFactory<? extends T>)
boundProviderFactory, source, scoping);
@@ -125,6 +133,7 @@
return true;
}
+ @Override
public Boolean visit(LinkedKeyBinding<? extends T> binding) {
prepareBinding();
Key<? extends T> linkedKey = binding.getLinkedKey();
@@ -141,18 +150,22 @@
return true;
}
+ @Override
public Boolean visit(UntargettedBinding<? extends T> untargetted) {
return false;
}
+ @Override
public Boolean visit(ExposedBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module
element");
}
-
+
+ @Override
public Boolean visit(ConvertedConstantBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module
element");
}
-
+
+ @Override
public Boolean visit(ProviderBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module
element");
}
=======================================
--- /core/src/com/google/inject/internal/BoundProviderFactory.java Thu Jul
7 17:34:16 2011
+++ /core/src/com/google/inject/internal/BoundProviderFactory.java Sun Feb
26 18:23:19 2012
@@ -16,6 +16,8 @@
package com.google.inject.internal;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.inject.Key;
import com.google.inject.internal.InjectorImpl.JitLimitation;
import com.google.inject.spi.Dependency;
@@ -27,6 +29,7 @@
*/
final class BoundProviderFactory<T> extends ProviderInternalFactory<T>
implements CreationListener {
+ private final ProvisionListenerStackCallback<T> provisionCallback;
private final InjectorImpl injector;
final Key<? extends javax.inject.Provider<? extends T>> providerKey;
private InternalFactory<? extends javax.inject.Provider<? extends T>>
providerFactory;
@@ -37,7 +40,8 @@
Object source,
boolean allowProxy,
ProvisionListenerStackCallback<T> provisionCallback) {
- super(source, allowProxy, provisionCallback);
+ super(source, allowProxy);
+ this.provisionCallback =
checkNotNull(provisionCallback, "provisionCallback");
this.injector = injector;
this.providerKey = providerKey;
}
@@ -56,7 +60,7 @@
try {
errors = errors.withSource(providerKey);
javax.inject.Provider<? extends T> provider =
providerFactory.get(errors, context, dependency, true);
- return circularGet(provider, errors, context, dependency, linked);
+ return circularGet(provider, errors, context, dependency, linked,
provisionCallback);
} finally {
context.popState();
}
=======================================
--- /core/src/com/google/inject/internal/ConstructorBindingImpl.java Thu
Jul 7 17:34:16 2011
+++ /core/src/com/google/inject/internal/ConstructorBindingImpl.java Sun
Feb 26 18:23:19 2012
@@ -127,7 +127,7 @@
factory.constructorInjector =
(ConstructorInjector<T>)
injector.constructors.get(constructorInjectionPoint, errors);
factory.provisionCallback =
- injector.provisionListenerStore.get(getKey());
+ injector.provisionListenerStore.get(this);
}
/** True if this binding has been initialized and is ready for use. */
=======================================
--- /core/src/com/google/inject/internal/ConstructorInjector.java Thu Jul
7 17:34:16 2011
+++ /core/src/com/google/inject/internal/ConstructorInjector.java Sun Feb
26 18:23:19 2012
@@ -81,6 +81,7 @@
return t;
}
+ constructionContext.startConstruction();
try {
// Optimization: Don't go through the callback stack if we have no
listeners.
if (!provisionCallback.hasListeners()) {
@@ -94,6 +95,7 @@
}
} finally {
constructionContext.removeCurrentReference();
+ constructionContext.finishConstruction();
}
}
@@ -101,7 +103,6 @@
private T provision(Errors errors, InternalContext context,
ConstructionContext<T> constructionContext) throws ErrorsException {
try {
- constructionContext.startConstruction();
T t;
try {
Object[] parameters = SingleParameterInjector.getAll(errors,
context, parameterInjectors);
=======================================
--- /core/src/com/google/inject/internal/InjectorImpl.java Tue Sep 13
10:41:32 2011
+++ /core/src/com/google/inject/internal/InjectorImpl.java Sun Feb 26
18:23:19 2012
@@ -548,7 +548,7 @@
// We do not pass cb.getInternalConstructor as the second
parameter
// so that cached exceptions while constructing it get stored.
// See TypeListenerTest#testTypeListenerThrows
- removeFailedJitBinding(key, null);
+ removeFailedJitBinding(binding, null);
cleanup(binding, new HashSet<Key>());
}
}
@@ -579,7 +579,7 @@
}
}
if(failed) {
- removeFailedJitBinding(depKey, ip);
+ removeFailedJitBinding(depBinding, ip);
bindingFailed = true;
}
} else if(state.getExplicitBinding(depKey) == null) {
@@ -593,11 +593,11 @@
}
/** Cleans up any state that may have been cached when constructing the
JIT binding. */
- private void removeFailedJitBinding(Key<?> key, InjectionPoint ip) {
- failedJitBindings.add(key);
- jitBindings.remove(key);
- membersInjectorStore.remove(key.getTypeLiteral());
- provisionListenerStore.remove(key);
+ private void removeFailedJitBinding(Binding<?> binding, InjectionPoint
ip) {
+ failedJitBindings.add(binding.getKey());
+ jitBindings.remove(binding.getKey());
+ membersInjectorStore.remove(binding.getKey().getTypeLiteral());
+ provisionListenerStore.remove(binding);
if(ip != null) {
constructors.remove(ip);
}
@@ -700,10 +700,9 @@
Key<? extends Provider<T>> providerKey = (Key<? extends Provider<T>>)
Key.get(providerType);
ProvidedByInternalFactory<T> internalFactory =
new ProvidedByInternalFactory<T>(rawType, providerType,
- providerKey, !options.disableCircularProxies,
- provisionListenerStore.get(key));
+ providerKey, !options.disableCircularProxies);
Object source = rawType;
- return LinkedProviderBindingImpl.createWithInitializer(
+ BindingImpl<T> binding =
LinkedProviderBindingImpl.createWithInitializer(
this,
key,
source,
@@ -711,6 +710,8 @@
scoping,
providerKey,
internalFactory);
+
internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding));
+ return binding;
}
/** Creates a binding for a type annotated with @ImplementedBy. */
=======================================
---
/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
Thu Jul 7 17:34:16 2011
+++
/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
Sun Feb 26 18:23:19 2012
@@ -30,19 +30,22 @@
*/
final class InternalFactoryToInitializableAdapter<T> extends
ProviderInternalFactory<T> {
+ private final ProvisionListenerStackCallback<T> provisionCallback;
private final Initializable<Provider<? extends T>> initializable;
public InternalFactoryToInitializableAdapter(
Initializable<Provider<? extends T>> initializable,
Object source, boolean allowProxy,
ProvisionListenerStackCallback<T> provisionCallback) {
- super(source, allowProxy, provisionCallback);
+ super(source, allowProxy);
+ this.provisionCallback =
checkNotNull(provisionCallback, "provisionCallback");
this.initializable = checkNotNull(initializable, "provider");
}
public T get(Errors errors, InternalContext context, Dependency<?>
dependency, boolean linked)
throws ErrorsException {
- return circularGet(initializable.get(errors), errors, context,
dependency, linked);
+ return circularGet(initializable.get(errors), errors, context,
dependency, linked,
+ provisionCallback);
}
@Override
=======================================
--- /core/src/com/google/inject/internal/ProvidedByInternalFactory.java Sun
Jun 26 14:02:54 2011
+++ /core/src/com/google/inject/internal/ProvidedByInternalFactory.java Sun
Feb 26 18:23:19 2012
@@ -37,22 +37,26 @@
private final Class<? extends Provider<?>> providerType;
private final Key<? extends Provider<T>> providerKey;
private BindingImpl<? extends Provider<T>> providerBinding;
+ private ProvisionListenerStackCallback<T> provisionCallback;
ProvidedByInternalFactory(
Class<?> rawType,
Class<? extends Provider<?>> providerType,
Key<? extends Provider<T>> providerKey,
- boolean allowProxy,
- ProvisionListenerStackCallback<T> provisionCallback) {
- super(providerKey, allowProxy, provisionCallback);
+ boolean allowProxy) {
+ super(providerKey, allowProxy);
this.rawType = rawType;
this.providerType = providerType;
this.providerKey = providerKey;
}
+
+ void setProvisionListenerCallback(ProvisionListenerStackCallback<T>
listener) {
+ provisionCallback = listener;
+ }
public void initialize(InjectorImpl injector, Errors errors) throws
ErrorsException {
providerBinding =
- injector.getBindingOrThrow(providerKey, errors,
JitLimitation.NEW_OR_EXISTING_JIT);
+ injector.getBindingOrThrow(providerKey, errors,
JitLimitation.NEW_OR_EXISTING_JIT);
}
@SuppressWarnings("unchecked")//
@@ -65,12 +69,13 @@
errors = errors.withSource(providerKey);
Provider provider = providerBinding.getInternalFactory().get(
errors, context, dependency, true);
- return circularGet(provider, errors, context, dependency, linked);
+ return circularGet(provider, errors, context, dependency, linked,
provisionCallback);
} finally {
context.popState();
}
}
+ @Override
protected T provision(javax.inject.Provider<? extends T> provider,
Errors errors,
Dependency<?> dependency, ConstructionContext<T> constructionContext)
throws ErrorsException {
=======================================
--- /core/src/com/google/inject/internal/ProviderInternalFactory.java Thu
Jul 7 17:34:16 2011
+++ /core/src/com/google/inject/internal/ProviderInternalFactory.java Sun
Feb 26 18:23:19 2012
@@ -32,19 +32,17 @@
*/
abstract class ProviderInternalFactory<T> implements InternalFactory<T> {
- private final ProvisionListenerStackCallback<T> provisionCallback;
private final boolean allowProxy;
protected final Object source;
- ProviderInternalFactory(Object source, boolean allowProxy,
- ProvisionListenerStackCallback<T> provisionCallback) {
- this.provisionCallback =
checkNotNull(provisionCallback, "provisionCallback");
+ ProviderInternalFactory(Object source, boolean allowProxy) {
this.source = checkNotNull(source, "source");
this.allowProxy = allowProxy;
}
protected T circularGet(final Provider<? extends T> provider, final
Errors errors,
- InternalContext context, final Dependency<?> dependency, boolean
linked)
+ InternalContext context, final Dependency<?> dependency, boolean
linked,
+ ProvisionListenerStackCallback<T> provisionCallback)
throws ErrorsException {
Class<?> expectedType =
dependency.getKey().getTypeLiteral().getRawType();
final ConstructionContext<T> constructionContext =
context.getConstructionContext(this);
@@ -62,14 +60,20 @@
}
// Optimization: Don't go through the callback stack if no one's
listening.
- if (!provisionCallback.hasListeners()) {
- return provision(provider, errors, dependency, constructionContext);
- } else {
- return provisionCallback.provision(errors, context, new
ProvisionCallback<T>() {
- public T call() throws ErrorsException {
- return provision(provider, errors, dependency,
constructionContext);
- }
- });
+ constructionContext.startConstruction();
+ try {
+ if (!provisionCallback.hasListeners()) {
+ return provision(provider, errors, dependency,
constructionContext);
+ } else {
+ return provisionCallback.provision(errors, context, new
ProvisionCallback<T>() {
+ public T call() throws ErrorsException {
+ return provision(provider, errors, dependency,
constructionContext);
+ }
+ });
+ }
+ } finally {
+ constructionContext.removeCurrentReference();
+ constructionContext.finishConstruction();
}
}
@@ -79,13 +83,8 @@
*/
protected T provision(Provider<? extends T> provider, Errors errors,
Dependency<?> dependency,
ConstructionContext<T> constructionContext) throws ErrorsException {
- constructionContext.startConstruction();
- try {
- T t = errors.checkForNull(provider.get(), source, dependency);
- constructionContext.setProxyDelegates(t);
- return t;
- } finally {
- constructionContext.finishConstruction();
- }
+ T t = errors.checkForNull(provider.get(), source, dependency);
+ constructionContext.setProxyDelegates(t);
+ return t;
}
}
=======================================
---
/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
Thu Jul 7 17:34:16 2011
+++
/core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
Sun Feb 26 18:23:19 2012
@@ -20,6 +20,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
+import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.spi.ProvisionListenerBinding;
@@ -35,11 +36,11 @@
final class ProvisionListenerCallbackStore {
private final ImmutableList<ProvisionListenerBinding> listenerBindings;
- private final Map<Key<?>, ProvisionListenerStackCallback<?>> cache
+ private final Map<KeyBinding, ProvisionListenerStackCallback<?>> cache
= new MapMaker().makeComputingMap(
- new Function<Key<?>, ProvisionListenerStackCallback<?>>() {
- public ProvisionListenerStackCallback<?> apply(Key<?> key) {
- return create(key);
+ new Function<KeyBinding, ProvisionListenerStackCallback<?>>() {
+ public ProvisionListenerStackCallback<?> apply(KeyBinding key)
{
+ return create(key.binding);
}
});
@@ -50,8 +51,8 @@
/** Returns a new {@link ProvisionListenerStackCallback} for the key.
*/
@SuppressWarnings("unchecked") // the ProvisionListenerStackCallback
type always agrees with the passed type
- public <T> ProvisionListenerStackCallback<T> get(Key<T> key) {
- return (ProvisionListenerStackCallback<T>) cache.get(key);
+ public <T> ProvisionListenerStackCallback<T> get(Binding<T> binding) {
+ return (ProvisionListenerStackCallback<T>) cache.get(new
KeyBinding(binding.getKey(), binding));
}
/**
@@ -63,7 +64,7 @@
*
* Returns true if the type was stored in the cache, false otherwise.
*/
- boolean remove(Key<?> type) {
+ boolean remove(Binding<?> type) {
return cache.remove(type) != null;
}
@@ -71,19 +72,39 @@
* Creates a new {@link ProvisionListenerStackCallback} with the correct
listeners
* for the key.
*/
- private <T> ProvisionListenerStackCallback<T> create(Key<T> key) {
+ private <T> ProvisionListenerStackCallback<T> create(Binding<T> binding)
{
List<ProvisionListener> listeners = null;
- for (ProvisionListenerBinding binding : listenerBindings) {
- if (binding.getKeyMatcher().matches(key)) {
+ for (ProvisionListenerBinding provisionBinding : listenerBindings) {
+ if (provisionBinding.getBindingMatcher().matches(binding)) {
if (listeners == null) {
listeners = Lists.newArrayList();
}
- listeners.addAll(binding.getListeners());
+ listeners.addAll(provisionBinding.getListeners());
}
}
if (listeners == null) {
listeners = ImmutableList.of();
}
- return new ProvisionListenerStackCallback<T>(key, listeners);
+ return new ProvisionListenerStackCallback<T>(binding, listeners);
+ }
+
+ /** A struct that holds key & binding but uses just key for
equality/hashcode. */
+ private static class KeyBinding {
+ final Key<?> key;
+ final Binding<?> binding;
+
+ KeyBinding(Key<?> key, Binding<?> binding) {
+ this.key = key;
+ this.binding = binding;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof KeyBinding &&
key.equals(((KeyBinding)obj).key);
+ }
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
}
}
=======================================
---
/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
Thu Jul 7 17:34:16 2011
+++
/core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
Sun Feb 26 18:23:19 2012
@@ -16,7 +16,7 @@
package com.google.inject.internal;
-import com.google.inject.Key;
+import com.google.inject.Binding;
import com.google.inject.ProvisionException;
import com.google.inject.spi.DependencyAndSource;
import com.google.inject.spi.ProvisionListener;
@@ -32,10 +32,10 @@
private static final ProvisionListener EMPTY_LISTENER[] = new
ProvisionListener[0];
private final ProvisionListener[] listeners;
- private final Key<T> key;
-
- public ProvisionListenerStackCallback(Key<T> key,
List<ProvisionListener> listeners) {
- this.key = key;
+ private final Binding<T> binding;
+
+ public ProvisionListenerStackCallback(Binding<T> binding,
List<ProvisionListener> listeners) {
+ this.binding = binding;
if (listeners.isEmpty()) {
this.listeners = EMPTY_LISTENER;
} else {
@@ -64,7 +64,7 @@
provision.erredListener.getClass() : "(unknown)";
throw errors
.errorInUserCode(caught, "Error notifying ProvisionListener %s
of %s.%n"
- + " Reason: %s", listener, key, caught)
+ + " Reason: %s", listener, binding.getKey(), caught)
.toException();
} else {
return provision.result;
@@ -105,6 +105,7 @@
} else if (index < listeners.length) {
int currentIdx = index;
try {
+
listeners[index].onProvision(this);
} catch(RuntimeException re) {
erredListener = listeners[currentIdx];
@@ -121,8 +122,11 @@
}
@Override
- public Key<T> getKey() {
- return key;
+ public Binding<T> getBinding() {
+ // TODO(sameb): Because so many places cast directly to BindingImpl
& subclasses,
+ // we can't decorate this to prevent calling getProvider().get(),
which means
+ // if someone calls that they'll get strange errors.
+ return binding;
}
@Override
=======================================
--- /core/src/com/google/inject/spi/DependencyAndSource.java Thu Jul 7
17:34:16 2011
+++ /core/src/com/google/inject/spi/DependencyAndSource.java Sun Feb 26
18:23:19 2012
@@ -16,7 +16,9 @@
package com.google.inject.spi;
+import com.google.inject.Binder;
import com.google.inject.Binding;
+import com.google.inject.Injector;
import com.google.inject.internal.util.StackTraceElements;
import java.lang.reflect.Member;
@@ -40,7 +42,7 @@
* Returns the Dependency, if one exists. For anything that can be
referenced
* by {@link Injector#getBinding}, a dependency exists. A dependency
will not
* exist (and this will return null) for types initialized with
- * {@link Binder#requestInjection} or {@link
Injector#injectMembers(Object),
+ * {@link Binder#requestInjection} or {@link
Injector#injectMembers(Object)},
* nor will it exist for objects injected into Providers bound with
* LinkedBindingBuilder#toProvider(Provider).
*/
=======================================
--- /core/src/com/google/inject/spi/Elements.java Thu Jul 7 17:34:16 2011
+++ /core/src/com/google/inject/spi/Elements.java Sun Feb 26 18:23:19 2012
@@ -208,8 +208,9 @@
elements.add(new TypeListenerBinding(getSource(), listener,
typeMatcher));
}
- public void bindListener(Matcher<? super Key<?>> keyMatcher,
ProvisionListener... listeners) {
- elements.add(new ProvisionListenerBinding(getSource(), keyMatcher,
listeners));
+ public void bindListener(Matcher<? super Binding<?>> bindingMatcher,
+ ProvisionListener... listeners) {
+ elements.add(new ProvisionListenerBinding(getSource(),
bindingMatcher, listeners));
}
public void requestStaticInjection(Class<?>... types) {
=======================================
--- /core/src/com/google/inject/spi/ProvisionListener.java Thu Jul 7
17:34:16 2011
+++ /core/src/com/google/inject/spi/ProvisionListener.java Sun Feb 26
18:23:19 2012
@@ -16,7 +16,7 @@
package com.google.inject.spi;
-import com.google.inject.Key;
+import com.google.inject.Binding;
import com.google.inject.Provider;
import com.google.inject.Scope;
@@ -50,13 +50,19 @@
/** Encapsulates a single act of provisioning.*/
public abstract static class ProvisionInvocation<T> {
- /** Returns the Key which will be provisioned. */
- public abstract Key<T> getKey();
+ /**
+ * Returns the Binding this is provisioning.
+ * <p>
+ * You must not call {@link Provider#get()} on the provider returned by
+ * {@link Binding#getProvider}, otherwise you will get confusing error
messages.
+ */
+ public abstract Binding<T> getBinding();
/** Performs the provision, returning the object provisioned. */
public abstract T provision();
/** Returns the dependency chain that led to this object being
provisioned. */
public abstract List<DependencyAndSource> getDependencyChain();
+
}
}
=======================================
--- /core/src/com/google/inject/spi/ProvisionListenerBinding.java Fri Jul
22 14:13:53 2011
+++ /core/src/com/google/inject/spi/ProvisionListenerBinding.java Sun Feb
26 18:23:19 2012
@@ -18,14 +18,14 @@
import com.google.common.collect.ImmutableList;
import com.google.inject.Binder;
-import com.google.inject.Key;
+import com.google.inject.Binding;
import com.google.inject.matcher.Matcher;
import java.util.List;
/**
* Binds keys (picked using a Matcher) to a provision listener. Listeners
are created explicitly in
- * a module using {@link Binder#bindListener(Matcher, ProvisionListener)}
statements:
+ * a module using {@link Binder#bindListener(Matcher,
ProvisionListener...)} statements:
*
* @author [email protected] (Sam Berlin)
* @since 4.0
@@ -33,14 +33,14 @@
public final class ProvisionListenerBinding implements Element {
private final Object source;
- private final Matcher<? super Key<?>> keyMatcher;
+ private final Matcher<? super Binding<?>> bindingMatcher;
private final List<ProvisionListener> listeners;
ProvisionListenerBinding(Object source,
- Matcher<? super Key<?>> typeMatcher,
+ Matcher<? super Binding<?>> bindingMatcher,
ProvisionListener[] listeners) {
this.source = source;
- this.keyMatcher = typeMatcher;
+ this.bindingMatcher = bindingMatcher;
this.listeners = ImmutableList.copyOf(listeners);
}
@@ -49,9 +49,11 @@
return listeners;
}
- /** Returns the key matcher which chooses which keys the listener should
be notified of. */
- public Matcher<? super Key<?>> getKeyMatcher() {
- return keyMatcher;
+ /**
+ * Returns the binding matcher which chooses which bindings the listener
should be notified of.
+ */
+ public Matcher<? super Binding<?>> getBindingMatcher() {
+ return bindingMatcher;
}
public Object getSource() {
@@ -63,7 +65,7 @@
}
public void applyTo(Binder binder) {
- binder.withSource(getSource()).bindListener(keyMatcher,
+ binder.withSource(getSource()).bindListener(bindingMatcher,
listeners.toArray(new ProvisionListener[listeners.size()]));
}
}
=======================================
--- /core/test/com/google/inject/ProvisionListenerTest.java Thu Jul 7
17:34:16 2011
+++ /core/test/com/google/inject/ProvisionListenerTest.java Sun Feb 26
18:23:19 2012
@@ -22,6 +22,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
@@ -282,6 +283,59 @@
assertNotNull(injector.getInstance(JitFoo.class));
assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
}
+
+ public void testSingletonMatcher() {
+ final Counter counter = new Counter();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindListener(new AbstractMatcher<Binding<?>>() {
+ @Override
+ public boolean matches(Binding<?> t) {
+ return Scopes.isSingleton(t);
+ }
+ }, counter);
+ }
+ });
+ assertEquals(0, counter.count);
+ // no increment for getting Many.
+ injector.getInstance(Many.class);
+ assertEquals(0, counter.count);
+ // but an increment for getting Sole, since it's a singleton.
+ injector.getInstance(Sole.class);
+ assertEquals(1, counter.count);
+ }
+
+ public void testCallingBindingDotGetProviderDotGet() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindListener(Matchers.any(), new ProvisionListener() {
+ @Override
+ public <T> void onProvision(ProvisionInvocation<T> provision) {
+ provision.getBinding().getProvider().get(); // AGH!
+ }
+ });
+ }
+ });
+
+ try {
+ injector.getInstance(Sole.class);
+ fail();
+ } catch(ProvisionException expected) {
+ // We don't really care what kind of error you get, we only care you
get an error.
+ }
+
+ try {
+ injector.getInstance(Many.class);
+ fail();
+ } catch(ProvisionException expected) {
+ // We don't really care what kind of error you get, we only care you
get an error.
+ }
+ }
+
+ @Singleton static class Sole {}
+ static class Many {}
@ImplementedBy(Foo.class) static interface JitFoo {}
@ProvidedBy(JitFoo2P.class) static class JitFoo2 {}
@@ -314,9 +368,9 @@
private static class Capturer implements ProvisionListener {
List<Key> keys = Lists.newArrayList();
public <T> void onProvision(ProvisionInvocation<T> provision) {
- keys.add(provision.getKey());
+ keys.add(provision.getBinding().getKey());
T provisioned = provision.provision();
- assertEquals(provision.getKey().getRawType(),
provisioned.getClass());
+ assertEquals(provision.getBinding().getKey().getRawType(),
provisioned.getClass());
}
List<Key> getAndClear() {
@@ -368,12 +422,17 @@
actual.add(dep.getDependency().getKey().getRawType());
}
assertEquals(expected, actual);
- provisionList.add(provision.getKey().getRawType());
+ provisionList.add(provision.getBinding().getKey().getRawType());
}
}
- private static Matcher<Object> keyMatcher(Class<?> clazz) {
- return Matchers.only(Key.get(clazz));
+ private static Matcher<Binding<?>> keyMatcher(final Class<?> clazz) {
+ return new AbstractMatcher<Binding<?>>() {
+ @Override
+ public boolean matches(Binding<?> t) {
+ return t.getKey().equals(Key.get(clazz));
+ }
+ };
}
@SuppressWarnings("unchecked")
@@ -389,7 +448,7 @@
bindListener(Matchers.any(), new ProvisionListener() {
public <T> void onProvision(ProvisionInvocation<T> provision) {
- totalList.add(provision.getKey().getRawType());
+ totalList.add(provision.getBinding().getKey().getRawType());
}
});
@@ -490,7 +549,7 @@
public <T> void onProvision(ProvisionInvocation<T> provision) {
notified.set(true);
- assertEquals(notifyType, provision.getKey().getRawType());
+ assertEquals(notifyType,
provision.getBinding().getKey().getRawType());
assertEquals(2, provision.getDependencyChain().size());
assertEquals(null,
provision.getDependencyChain().get(0).getDependency());
--
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en.