获取lambda
2023-02-18 16:34:50 时间
处世让一步为高,退步即进步的张本;待人宽一分是福利人利己的根基。——洪自诚
昨天说了获取lambda代理
今天获取实际lambda
对象
重要的是这个函数java.lang.invoke.LambdaMetafactory#metafactory
以及altMetafactory
我们在昨天的基础上,进行获取
@Test
@SneakyThrows
void testVirtual() {
final MethodHandle virtual = MethodHandles.lookup().findVirtual(LambdaExecutable.class, "getName", MethodType.methodType(String.class));
final SerFunc<LambdaExecutable, String> proxy = MethodHandleProxies.asInterfaceInstance(SerFunc.class, virtual);
InvocationHandler handler = Proxy.getInvocationHandler(proxy);
MethodHandle methodHandle = ReflectHelper.getFieldValue(handler, "val$target");
final CallSite callSite = LambdaMetafactory.altMetafactory(
MethodHandles.lookup(),
"apply",
MethodType.methodType(SerFunc.class),
MethodType.methodType(Object.class, Object.class),
methodHandle,
MethodType.methodType(String.class, LambdaExecutable.class),
LambdaMetafactory.FLAG_SERIALIZABLE
);
final MethodHandle target = callSite.getTarget();
final SerFunc<LambdaExecutable, String> invoke = (SerFunc<LambdaExecutable, String>) target.invoke();
final LambdaExecutable executable = new LambdaExecutable();
executable.setName("test");
Assertions.assertEquals("test", invoke.apply(executable));
Assertions.assertEquals("getName", LambdaHelper.resolve(invoke).getName());
}
进一步封装后:
public static <T> T revert(Class<T> clazz, Executable executable) {
final Method funcMethod = Steam.of(clazz.getMethods()).findFirst(method -> Modifier.isAbstract(method.getModifiers()))
.orElseThrow(() -> new UtilException("not a functional interface"));
final MethodHandle implMethod;
final MethodType instantiatedMethodType;
if (executable instanceof Method) {
final Method method = (Method) executable;
implMethod = ((SerSupp<MethodHandle>) () -> MethodHandles.lookup().unreflect(method)).get();
instantiatedMethodType = MethodType.methodType(method.getReturnType(), method.getDeclaringClass(), method.getParameterTypes());
} else {
final Constructor<?> constructor = (Constructor<?>) executable;
implMethod = ((SerSupp<MethodHandle>) () -> MethodHandles.lookup().unreflectConstructor(constructor)).get();
instantiatedMethodType = MethodType.methodType(constructor.getDeclaringClass(), constructor.getParameterTypes());
}
final CallSite callSite = ((SerSupp<CallSite>) () ->
Serializable.class.isAssignableFrom(clazz) ?
LambdaMetafactory.altMetafactory(
MethodHandles.lookup(),
funcMethod.getName(),
MethodType.methodType(clazz),
MethodType.methodType(funcMethod.getReturnType(), funcMethod.getParameterTypes()),
implMethod,
instantiatedMethodType,
LambdaMetafactory.FLAG_SERIALIZABLE
) :
LambdaMetafactory.metafactory(
MethodHandles.lookup(),
funcMethod.getName(),
MethodType.methodType(clazz),
MethodType.methodType(funcMethod.getReturnType(), funcMethod.getParameterTypes()),
implMethod,
instantiatedMethodType
)
).get();
final MethodHandle target = callSite.getTarget();
return ((SerSupp<T>) () -> SerFunc.<Object, T>cast().apply(target.invoke())).get();
}
使用方式:
@Test
void testRevert() {
final LambdaExecutable getName = LambdaHelper.<SerFunc<LambdaExecutable, String>>resolve(LambdaExecutable::getName);
final SerFunc<LambdaExecutable, String> revertedGetName = LambdaHelper.revert(SerFunc.class, getName.getExecutable());
Assertions.assertEquals(revertedGetName.apply(getName), getName.getName());
final LambdaExecutable constructor = LambdaHelper.<SerSupp<LambdaExecutable>>resolve(LambdaExecutable::new);
final SerSupp<LambdaExecutable> revertedConstructor = LambdaHelper.revert(SerSupp.class, constructor.getExecutable());
Assertions.assertEquals(LambdaExecutable.class, revertedConstructor.get().getClass());
}
相关文章
- NGINX日志切割
- Nginx 的配置文件 nginx.conf
- Acrobat 8安装步骤-所有版本的Acrobat PDF编辑器
- Acrobat 9 Pro软件安装教程-所有版本的Acrobat PDF编辑器
- Adobe Acrobat DC2020(PDF 阅读、编辑、转换-所有版本的Acrobat PDF编辑器 Adobe Acrobat Pro DC 2020是
- Adobe Acrobat 9 Pro安装破解法(附下载地址)-所有版本的Acrobat PDF编辑器
- CleanMyMac2023最新版激活安装下载教程
- FL2023中文版水果软件下载Fruity Loop Studio21
- 解决Ubuntu系统无法连接网络
- 『教程』首页及文章页滚动广告栏
- Redhat8.0本地Yum源配置方法
- XDD-PLUS登录不上或者登录失败解决方法
- PanDalMG(熊猫图床)一款全新的国内公益图床
- 傻妞机器人最新版安装教程
- docker容器打包成镜像
- 挖矿木马自助清理手册
- 把程序制作成docker镜像
- 01-k8s集群搭建-基础环境准备
- 免费获得Office365
- 续订Office365E5订阅