mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
!960 [enhancement] 使LambdaFactory.build支持构造器
Merge pull request !960 from 阿超/v6-dev
This commit is contained in:
commit
d9cd597256
@ -7,9 +7,12 @@ import cn.hutool.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.core.map.WeakConcurrentMap;
|
||||
import cn.hutool.core.reflect.LookupFactory;
|
||||
import cn.hutool.core.reflect.MethodUtil;
|
||||
import cn.hutool.core.reflect.ReflectUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
@ -31,7 +34,7 @@ public class LambdaFactory {
|
||||
throw new IllegalAccessException();
|
||||
}
|
||||
|
||||
private static final Map<MutableEntry<Class<?>, Method>, Object> CACHE = new WeakConcurrentMap<>();
|
||||
private static final Map<MutableEntry<Class<?>, Executable>, Object> CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 构建Lambda
|
||||
@ -61,30 +64,37 @@ public class LambdaFactory {
|
||||
* 构建Lambda
|
||||
*
|
||||
* @param functionInterfaceType 接受Lambda的函数式接口类型
|
||||
* @param method 方法对象
|
||||
* @param executable 方法对象,支持构造器
|
||||
* @param <F> Function类型
|
||||
* @return 接受Lambda的函数式接口对象
|
||||
* @param <F> Function类型
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <F> F build(final Class<F> functionInterfaceType, final Method method) {
|
||||
public static <F> F build(final Class<F> functionInterfaceType, final Executable executable) {
|
||||
Assert.notNull(functionInterfaceType);
|
||||
Assert.notNull(method);
|
||||
final MutableEntry<Class<?>, Method> cacheKey = new MutableEntry<>(functionInterfaceType, method);
|
||||
Assert.notNull(executable);
|
||||
final MutableEntry<Class<?>, Executable> cacheKey = new MutableEntry<>(functionInterfaceType, executable);
|
||||
return (F) CACHE.computeIfAbsent(cacheKey, key -> {
|
||||
final List<Method> abstractMethods = Arrays.stream(functionInterfaceType.getMethods())
|
||||
.filter(m -> Modifier.isAbstract(m.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口");
|
||||
if (!method.isAccessible()) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
ReflectUtil.setAccessible(executable);
|
||||
final Method invokeMethod = abstractMethods.get(0);
|
||||
final MethodHandles.Lookup caller = LookupFactory.lookup(method.getDeclaringClass());
|
||||
final MethodHandles.Lookup caller = LookupFactory.lookup(executable.getDeclaringClass());
|
||||
final String invokeName = invokeMethod.getName();
|
||||
final MethodType invokedType = methodType(functionInterfaceType);
|
||||
final MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes());
|
||||
final MethodHandle implMethod = Opt.ofTry(() -> caller.unreflect(method)).get();
|
||||
final MethodType insMethodType = methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
|
||||
final MethodHandle implMethod;
|
||||
final MethodType instantiatedMethodType;
|
||||
if (executable instanceof Method) {
|
||||
final Method method = (Method) executable;
|
||||
implMethod = ((SerSupplier<MethodHandle>) () -> MethodHandles.lookup().unreflect(method)).get();
|
||||
instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
|
||||
} else {
|
||||
final Constructor<?> constructor = (Constructor<?>) executable;
|
||||
implMethod = ((SerSupplier<MethodHandle>) () -> MethodHandles.lookup().unreflectConstructor(constructor)).get();
|
||||
instantiatedMethodType = MethodType.methodType(constructor.getDeclaringClass(), constructor.getParameterTypes());
|
||||
}
|
||||
final boolean isSerializable = Serializable.class.isAssignableFrom(functionInterfaceType);
|
||||
try {
|
||||
final CallSite callSite = isSerializable ?
|
||||
@ -94,7 +104,7 @@ public class LambdaFactory {
|
||||
invokedType,
|
||||
samMethodType,
|
||||
implMethod,
|
||||
insMethodType,
|
||||
instantiatedMethodType,
|
||||
FLAG_SERIALIZABLE
|
||||
) :
|
||||
LambdaMetafactory.metafactory(
|
||||
@ -103,7 +113,7 @@ public class LambdaFactory {
|
||||
invokedType,
|
||||
samMethodType,
|
||||
implMethod,
|
||||
insMethodType
|
||||
instantiatedMethodType
|
||||
);
|
||||
//noinspection unchecked
|
||||
return (F) callSite.getTarget().invoke();
|
||||
|
@ -12,11 +12,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.lang.invoke.LambdaConversionException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleProxies;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -24,6 +21,7 @@ import java.util.Comparator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author nasodaengineer
|
||||
@ -160,6 +158,15 @@ public class LambdaFactoryTest {
|
||||
loop(count, tasks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor() {
|
||||
Constructor<Something> constructor = ((SerSupplier<Constructor<Something>>) Something.class::getConstructor).get();
|
||||
Supplier<Something> constructorLambda = LambdaFactory.build(Supplier.class, constructor);
|
||||
// constructorLambda can be cache or transfer
|
||||
Something something = constructorLambda.get();
|
||||
Assert.assertEquals(Something.class, something.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>hardCode 运行1次耗时 7600 NANOSECONDS
|
||||
* <p>lambda 运行1次耗时 12400 NANOSECONDS
|
||||
|
Loading…
x
Reference in New Issue
Block a user