This commit is contained in:
Looly 2023-04-22 03:27:06 +08:00
parent 16e05bf9f5
commit 79fc3663fb
3 changed files with 46 additions and 23 deletions

View File

@ -82,7 +82,7 @@ public class LambdaFactory {
} }
/** /**
* 根据提供的方法或构造对象构建对应的Lambda函数<br> * 根据提供的方法或构造对象构建对应的Lambda函数即通过Lambda函数代理方法或构造<br>
* 调用函数相当于执行对应的方法或构造 * 调用函数相当于执行对应的方法或构造
* *
* @param funcType 接受Lambda的函数式接口类型 * @param funcType 接受Lambda的函数式接口类型
@ -94,40 +94,45 @@ public class LambdaFactory {
private static <F> F doBuildWithoutCache(final Class<F> funcType, final Executable executable) { private static <F> F doBuildWithoutCache(final Class<F> funcType, final Executable executable) {
ReflectUtil.setAccessible(executable); ReflectUtil.setAccessible(executable);
// 获取Lambda函数
final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract);
Assert.equals(abstractMethods.length, 1, "不支持非函数式接口");
final Method invokeMethod = abstractMethods[0];
try { try {
return (F) metaFactory(funcType, executable).getTarget().invoke(); return (F) metaFactory(funcType, invokeMethod, executable)
.getTarget().invoke();
} catch (final Throwable e) { } catch (final Throwable e) {
throw new HutoolException(e); throw new HutoolException(e);
} }
} }
/** /**
* 使用给定的函数接口代理指定方法或构造 * 通过Lambda函数代理方法或构造
* *
* @param functionInterfaceType 函数接口 * @param funcType 函数类型
* @param executable 方法或构造 * @param invokeMethod 函数执行的方法
* @return 函数锚点 * @param executable 被代理的方法或构造
* @return {@link CallSite}
* @throws LambdaConversionException 权限等异常 * @throws LambdaConversionException 权限等异常
*/ */
private static CallSite metaFactory(final Class<?> functionInterfaceType, final Executable executable) throws LambdaConversionException { private static CallSite metaFactory(final Class<?> funcType, final Method invokeMethod,
// 被代理的方法 final Executable executable) throws LambdaConversionException {
final Method[] abstractMethods = MethodUtil.getPublicMethods(functionInterfaceType, ModifierUtil::isAbstract); final MethodHandles.Lookup caller = LookupUtil.lookup(executable.getDeclaringClass());
Assert.equals(abstractMethods.length, 1, "Class is not a functional interface.");
final Method invokeMethod = abstractMethods[0];
final MethodHandle methodHandle = LookupUtil.unreflect(executable);
final MethodHandles.Lookup caller = LookupUtil.lookup();
final String invokeName = invokeMethod.getName(); final String invokeName = invokeMethod.getName();
final MethodType invokedType = MethodType.methodType(functionInterfaceType); final MethodType invokedType = MethodType.methodType(funcType);
final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), invokeMethod.getParameterTypes());
if(ClassUtil.isSerializable(functionInterfaceType)){ // 对入参做检查原始类型转换为包装类型
final Class<?>[] paramTypes = invokeMethod.getParameterTypes();
final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), paramTypes);
if (ClassUtil.isSerializable(funcType)) {
return LambdaMetafactory.altMetafactory( return LambdaMetafactory.altMetafactory(
caller, caller,
invokeName, invokeName,
invokedType, invokedType,
samMethodType, samMethodType,
methodHandle, LookupUtil.unreflect(executable),
MethodTypeUtil.methodType(executable), MethodTypeUtil.methodType(executable),
LambdaMetafactory.FLAG_SERIALIZABLE LambdaMetafactory.FLAG_SERIALIZABLE
); );
@ -138,7 +143,7 @@ public class LambdaFactory {
invokeName, invokeName,
invokedType, invokedType,
samMethodType, samMethodType,
methodHandle, LookupUtil.unreflect(executable),
MethodTypeUtil.methodType(executable) MethodTypeUtil.methodType(executable)
); );
} }

View File

@ -1,5 +1,6 @@
package org.dromara.hutool.core.io.file; package org.dromara.hutool.core.io.file;
import org.dromara.hutool.core.array.ArrayUtil;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -69,7 +70,13 @@ public class PathUtilTest {
@Test @Test
public void getMimeOfRarTest(){ public void getMimeOfRarTest(){
final String contentType = FileUtil.getMimeType("a001.rar"); final String contentType = FileUtil.getMimeType("a001.rar");
Assertions.assertEquals("application/x-rar-compressed", contentType); Assertions.assertTrue(
ArrayUtil.contains(
new String[]{
"application/x-rar-compressed",
// JDK9+修改为此
"application/vnd.rar"},
contentType));
} }
@Test @Test

View File

@ -180,6 +180,17 @@ public class LambdaUtilTest {
Assertions.assertTrue(bean.isFlag()); Assertions.assertTrue(bean.isFlag());
} }
@Test
void buildSetterTest() {
final Bean bean = new Bean();
bean.setId(2L);
bean.setFlag(false);
final BiConsumer<Bean, Object> setter = LambdaUtil.buildSetter(Bean.class, "flag");
setter.accept(bean, true);
Assertions.assertTrue(bean.isFlag());
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void lambdaTest() { public void lambdaTest() {