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(functionInterfaceType);
Assert.notNull(method); Assert.notNull(method);
Tuple cacheKey = new Tuple(functionInterfaceType, method); Tuple cacheKey = new Tuple(functionInterfaceType, method);
Object cacheValue = CACHE.get(cacheKey); //noinspection unchecked
if (null != cacheValue) { return (F) CACHE.computeIfAbsent(cacheKey, key -> {
//noinspection unchecked List<Method> abstractMethods = Arrays.stream(functionInterfaceType.getMethods())
return (F) cacheValue; .filter(m -> Modifier.isAbstract(m.getModifiers()))
} .collect(Collectors.toList());
List<Method> abstractMethods = Arrays.stream(functionInterfaceType.getMethods()) Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口");
.filter(m -> Modifier.isAbstract(m.getModifiers())) if (!method.isAccessible()) {
.collect(Collectors.toList()); method.setAccessible(true);
Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口"); }
if (!method.isAccessible()) { Method invokeMethod = abstractMethods.get(0);
method.setAccessible(true); MethodHandles.Lookup caller = LookupFactory.lookup(method.getDeclaringClass());
} String invokeName = invokeMethod.getName();
Method invokeMethod = abstractMethods.get(0); MethodType invokedType = methodType(functionInterfaceType);
MethodHandles.Lookup caller = LookupFactory.lookup(method.getDeclaringClass()); MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes());
String invokeName = invokeMethod.getName(); MethodHandle implMethod = Opt.ofTry(() -> caller.unreflect(method)).get();
MethodType invokedType = methodType(functionInterfaceType); MethodType insMethodType = methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
MethodType samMethodType = methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes()); boolean isSerializable = Arrays.stream(functionInterfaceType.getInterfaces()).anyMatch(i -> i.isAssignableFrom(Serializable.class));
MethodHandle implMethod = Opt.ofTry(() -> caller.unreflect(method)).get(); CallSite callSite = Opt.ofTry(() -> isSerializable ?
MethodType insMethodType = methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes()); LambdaMetafactory.altMetafactory(
boolean isSerializable = Arrays.stream(functionInterfaceType.getInterfaces()).anyMatch(i -> i.isAssignableFrom(Serializable.class)); caller,
CallSite callSite = Opt.ofTry(() -> isSerializable ? invokeName,
LambdaMetafactory.altMetafactory( invokedType,
caller, samMethodType,
invokeName, implMethod,
invokedType, insMethodType,
samMethodType, FLAG_SERIALIZABLE
implMethod, ) :
insMethodType, LambdaMetafactory.metafactory(
FLAG_SERIALIZABLE caller,
) : invokeName,
LambdaMetafactory.metafactory( invokedType,
caller, samMethodType,
invokeName, implMethod,
invokedType, insMethodType
samMethodType, )).get();
implMethod,
insMethodType try {
)).get(); //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);
}
} }
} }