76 lines
3.0 KiB
Java
76 lines
3.0 KiB
Java
package tc.oc.commons.core.util;
|
|
|
|
import java.lang.reflect.InvocationHandler;
|
|
import java.lang.reflect.Proxy;
|
|
import java.util.Collection;
|
|
import javax.inject.Provider;
|
|
|
|
import com.google.inject.TypeLiteral;
|
|
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
public class ProxyUtils {
|
|
private ProxyUtils() {}
|
|
|
|
public static <T> T newProxy(Class<T> type, InvocationHandler handler) {
|
|
return newProxy(type, handler, type.getClassLoader());
|
|
}
|
|
|
|
public static <T> T newProxy(Class<T> type, InvocationHandler handler, ClassLoader classLoader) {
|
|
return (T) Proxy.newProxyInstance(
|
|
checkNotNull(classLoader),
|
|
new Class<?>[]{checkNotNull(type)},
|
|
checkNotNull(handler)
|
|
);
|
|
}
|
|
|
|
public static <T> T newProxy(Class<T> proxyType, Collection<? extends Class<?>> interfaces, InvocationHandler handler) {
|
|
return newProxy(proxyType, interfaces, handler, proxyType.getClassLoader());
|
|
}
|
|
|
|
public static <T> T newProxy(Class<T> proxyType, Collection<? extends Class<?>> interfaces, InvocationHandler handler, ClassLoader classLoader) {
|
|
// proxyType must be first in the interface list, so any method that it declares
|
|
// will always be resolved to it, rather than a possible override in another interface.
|
|
final Class[] array = new Class<?>[1 + interfaces.size()];
|
|
array[0] = proxyType;
|
|
ArrayUtils.copy(interfaces, array, 1);
|
|
|
|
return (T) Proxy.newProxyInstance(
|
|
checkNotNull(classLoader),
|
|
array,
|
|
checkNotNull(handler)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Return a generated implementation of {@link T} that delegates all method calls
|
|
* to the instance returned by the given {@link Provider}. The provider is called
|
|
* for every method invocation.
|
|
*
|
|
* The provider's {@link ClassLoader} is used to load the generated class.
|
|
*/
|
|
public static <T> T newProviderProxy(Class<T> type, Provider<T> provider) {
|
|
return newProxy(type, MethodHandleInvoker.dynamic(provider));
|
|
}
|
|
|
|
public static <T> T newProviderProxy(Class<T> type, Collection<? extends Class<?>> interfaces, Provider<T> provider) {
|
|
return newProxy(type, interfaces, MethodHandleInvoker.dynamic(provider));
|
|
}
|
|
|
|
public static <T> T newProviderProxy(TypeLiteral<T> type, Provider<T> provider) {
|
|
return newProviderProxy((Class<T>) type.getRawType(), provider);
|
|
}
|
|
|
|
/**
|
|
* Return a generated implementation of {@link T} that delegates all method calls
|
|
* to the instance returned by the given {@link Provider}. That instance is not
|
|
* retrieved until the first time a method is called, after which the returned
|
|
* instance is cached and reused forever.
|
|
*
|
|
* The provider's {@link ClassLoader} is used to load the generated class.
|
|
*/
|
|
public static <T> T newCachingProviderProxy(Class<T> type, Provider<T> provider) {
|
|
return newProxy(type, MethodHandleInvoker.caching(provider));
|
|
}
|
|
}
|