ProjectAres/Util/core/src/main/java/tc/oc/commons/core/util/ProxyUtils.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));
}
}