com.google.inject.internal.ConstructionContext Maven / Gradle / Ivy
package com.google.inject.internal;
import com.google.inject.internal.InjectorImpl.InjectorOptions;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* Context of a dependency construction. Used to manage circular references.
*/
final class ConstructionContext {
T currentReference;
boolean constructing;
List> invocationHandlers;
public T getCurrentReference() {
return currentReference;
}
public void setCurrentReference(T currentReference) {
this.currentReference = currentReference;
}
public void removeCurrentReference() {
this.currentReference = null;
}
public boolean isConstructing() {
return constructing;
}
public void startConstruction() {
this.constructing = true;
}
public void finishConstruction() {
this.constructing = false;
invocationHandlers = null;
}
public Object createProxy(InjectorOptions injectorOptions,
Class> expectedType) throws InternalProvisionException {
if (injectorOptions.disableCircularProxies) {
throw InternalProvisionException.circularDependenciesDisabled(expectedType);
}
if (!expectedType.isInterface()) {
throw InternalProvisionException.cannotProxyClass(expectedType);
}
if (invocationHandlers == null) {
invocationHandlers = new ArrayList<>();
}
DelegatingInvocationHandler invocationHandler = new DelegatingInvocationHandler<>();
invocationHandlers.add(invocationHandler);
ClassLoader classLoader = expectedType.getClass().getClassLoader() != null ?
expectedType.getClass().getClassLoader() : ClassLoader.getSystemClassLoader();
return expectedType.cast(Proxy.newProxyInstance(classLoader,
new Class>[]{expectedType, CircularDependencyProxy.class}, invocationHandler));
}
public void setProxyDelegates(T delegate) {
if (invocationHandlers != null) {
for (DelegatingInvocationHandler handler : invocationHandlers) {
handler.setDelegate(delegate);
}
// initialization of each handler can happen no more than once
invocationHandlers = null;
}
}
}