/*
* Copyright (C) 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.inject;
import com.google.inject.internal.CircularDependencyProxy;
import com.google.inject.internal.LinkedBindingImpl;
import com.google.inject.internal.SingletonScope;
import com.google.inject.spi.BindingScopingVisitor;
import com.google.inject.spi.ExposedBinding;
import java.lang.annotation.Annotation;
Built-in scope implementations.
Author: crazybob@google.com (Bob Lee)
/**
* Built-in scope implementations.
*
* @author crazybob@google.com (Bob Lee)
*/
public class Scopes {
private Scopes() {}
/** One instance per {@link Injector}. Also see {@code @}{@link Singleton}. */
public static final Scope SINGLETON = new SingletonScope();
No scope; the same as not applying any scope at all. Each time the Injector obtains an instance
of an object with "no scope", it injects this instance then immediately forgets it. When the
next request for the same binding arrives it will need to obtain the instance over again.
This exists only in case a class has been annotated with a scope annotation such as @Singleton
, and you need to override this to "no scope" in your binding.
Since: 2.0
/**
* No scope; the same as not applying any scope at all. Each time the Injector obtains an instance
* of an object with "no scope", it injects this instance then immediately forgets it. When the
* next request for the same binding arrives it will need to obtain the instance over again.
*
* <p>This exists only in case a class has been annotated with a scope annotation such as {@link
* Singleton @Singleton}, and you need to override this to "no scope" in your binding.
*
* @since 2.0
*/
public static final Scope NO_SCOPE =
new Scope() {
@Override
public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
return unscoped;
}
@Override
public String toString() {
return "Scopes.NO_SCOPE";
}
};
private static final BindingScopingVisitor<Boolean> IS_SINGLETON_VISITOR =
new BindingScopingVisitor<Boolean>() {
@Override
public Boolean visitNoScoping() {
return false;
}
@Override
public Boolean visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
return scopeAnnotation == Singleton.class
|| scopeAnnotation == javax.inject.Singleton.class;
}
@Override
public Boolean visitScope(Scope scope) {
return scope == Scopes.SINGLETON;
}
@Override
public Boolean visitEagerSingleton() {
return true;
}
};
Returns true if binding
is singleton-scoped. If the binding is a linked key binding
and belongs to an injector (ie. it was retrieved via Injector.getBinding()
), then this method will also true if the target binding is singleton-scoped. Since: 3.0
/**
* Returns true if {@code binding} is singleton-scoped. If the binding is a {@link
* com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
* was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
* also true if the target binding is singleton-scoped.
*
* @since 3.0
*/
public static boolean isSingleton(Binding<?> binding) {
do {
boolean singleton = binding.acceptScopingVisitor(IS_SINGLETON_VISITOR);
if (singleton) {
return true;
}
if (binding instanceof LinkedBindingImpl) {
LinkedBindingImpl<?> linkedBinding = (LinkedBindingImpl) binding;
Injector injector = linkedBinding.getInjector();
if (injector != null) {
binding = injector.getBinding(linkedBinding.getLinkedKey());
continue;
}
} else if (binding instanceof ExposedBinding) {
ExposedBinding<?> exposedBinding = (ExposedBinding) binding;
Injector injector = exposedBinding.getPrivateElements().getInjector();
if (injector != null) {
binding = injector.getBinding(exposedBinding.getKey());
continue;
}
}
return false;
} while (true);
}
Returns true if binding
has the given scope. If the binding is a linked key binding
and belongs to an injector (ie. it was retrieved via Injector.getBinding()
), then this method will also true if the target binding has the given scope. Params: - binding – binding to check
- scope – scope implementation instance
- scopeAnnotation – scope annotation class
Since: 4.0
/**
* Returns true if {@code binding} has the given scope. If the binding is a {@link
* com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it
* was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will
* also true if the target binding has the given scope.
*
* @param binding binding to check
* @param scope scope implementation instance
* @param scopeAnnotation scope annotation class
* @since 4.0
*/
public static boolean isScoped(
Binding<?> binding, final Scope scope, final Class<? extends Annotation> scopeAnnotation) {
do {
boolean matches =
binding.acceptScopingVisitor(
new BindingScopingVisitor<Boolean>() {
@Override
public Boolean visitNoScoping() {
return false;
}
@Override
public Boolean visitScopeAnnotation(Class<? extends Annotation> visitedAnnotation) {
return visitedAnnotation == scopeAnnotation;
}
@Override
public Boolean visitScope(Scope visitedScope) {
return visitedScope == scope;
}
@Override
public Boolean visitEagerSingleton() {
return false;
}
});
if (matches) {
return true;
}
if (binding instanceof LinkedBindingImpl) {
LinkedBindingImpl<?> linkedBinding = (LinkedBindingImpl) binding;
Injector injector = linkedBinding.getInjector();
if (injector != null) {
binding = injector.getBinding(linkedBinding.getLinkedKey());
continue;
}
} else if (binding instanceof ExposedBinding) {
ExposedBinding<?> exposedBinding = (ExposedBinding) binding;
Injector injector = exposedBinding.getPrivateElements().getInjector();
if (injector != null) {
binding = injector.getBinding(exposedBinding.getKey());
continue;
}
}
return false;
} while (true);
}
Returns true if the object is a proxy for a circular dependency, constructed by Guice because
it encountered a circular dependency. Scope implementations should be careful to not cache
circular proxies, because the proxies are not intended for general purpose use. (They are
designed just to fulfill the immediate injection, not all injections. Caching them can lead to
IllegalArgumentExceptions or ClassCastExceptions.)
Since: 4.0
/**
* Returns true if the object is a proxy for a circular dependency, constructed by Guice because
* it encountered a circular dependency. Scope implementations should be careful to <b>not cache
* circular proxies</b>, because the proxies are not intended for general purpose use. (They are
* designed just to fulfill the immediate injection, not all injections. Caching them can lead to
* IllegalArgumentExceptions or ClassCastExceptions.)
*
* @since 4.0
*/
public static boolean isCircularProxy(Object object) {
return object instanceof CircularDependencyProxy;
}
}