perf(core): 改用线程安全的方式从缓存中获取lambda对象

This commit is contained in:
wy 2022-12-11 10:46:29 +08:00
parent 58d28c0767
commit 74db3733a2

View File

@ -66,52 +66,49 @@ public class LambdaFactory {
Assert.notNull(functionInterfaceType);
Assert.notNull(method);
Tuple cacheKey = new Tuple(functionInterfaceType, method);
Object cacheValue = CACHE.get(cacheKey);
if (null != cacheValue) {
//noinspection unchecked
return (F) cacheValue;
}
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);
}
Method invokeMethod = abstractMethods.get(0);
MethodHandles.Lookup caller = LookupFactory.lookup(method.getDeclaringClass());
String invokeName = invokeMethod.getName();
MethodType invokedType = methodType(functionInterfaceType);
MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes());
MethodHandle implMethod = Opt.ofTry(() -> caller.unreflect(method)).get();
MethodType insMethodType = methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
boolean isSerializable = Arrays.stream(functionInterfaceType.getInterfaces()).anyMatch(i -> i.isAssignableFrom(Serializable.class));
CallSite callSite = Opt.ofTry(() -> isSerializable ?
LambdaMetafactory.altMetafactory(
caller,
invokeName,
invokedType,
samMethodType,
implMethod,
insMethodType,
FLAG_SERIALIZABLE
) :
LambdaMetafactory.metafactory(
caller,
invokeName,
invokedType,
samMethodType,
implMethod,
insMethodType
)).get();
//noinspection unchecked
return (F) CACHE.computeIfAbsent(cacheKey, key -> {
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);
}
Method invokeMethod = abstractMethods.get(0);
MethodHandles.Lookup caller = LookupFactory.lookup(method.getDeclaringClass());
String invokeName = invokeMethod.getName();
MethodType invokedType = methodType(functionInterfaceType);
MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes());
MethodHandle implMethod = Opt.ofTry(() -> caller.unreflect(method)).get();
MethodType insMethodType = methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
boolean isSerializable = Arrays.stream(functionInterfaceType.getInterfaces()).anyMatch(i -> i.isAssignableFrom(Serializable.class));
CallSite callSite = Opt.ofTry(() -> isSerializable ?
LambdaMetafactory.altMetafactory(
caller,
invokeName,
invokedType,
samMethodType,
implMethod,
insMethodType,
FLAG_SERIALIZABLE
) :
LambdaMetafactory.metafactory(
caller,
invokeName,
invokedType,
samMethodType,
implMethod,
insMethodType
)).get();
try {
//noinspection unchecked
return (F) callSite.getTarget().invoke();
} catch (Throwable e) {
throw new RuntimeException(e);
}
});
try {
//noinspection unchecked
F lambda = (F) callSite.getTarget().invoke();
CACHE.put(cacheKey, lambda);
return lambda;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}