Я пытаюсь использовать LambdaMetafactory для замены отражения, но у меня есть проблема. Если я использую определенный класс, он работает хорошо, вот так:
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType type = MethodType.methodType(ResponseMsg.class,Map.class);
MethodHandle mh = lookup.findVirtual(TestService.class,"testMethod",type);
TestService ins = TestService.getInstance();
MethodHandle factory = LambdaMetafactory.metafactory(
lookup, "apply", MethodType.methodType(Function.class,TestService.class),
type.generic(), mh, type).getTarget();
factory.bindTo(ins);
Function lambda = (Function) factory.invokeExact(ins);
Но если я использую Class<?>
для замены определенного класса, тогда он не будет работать, так:
public static Function generateLambda(@NotNull Class<?> cls,@NotNull String method) {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType type = MethodType.methodType(RETURN_TYPE,PARM_TYPE);
try {
MethodHandle mh = lookup.findVirtual(cls,method,type);
Object instance = getInstance(cls);
if(instance == null) {
return null;
}
MethodHandle factory = LambdaMetafactory.metafactory(
lookup, "apply", MethodType.methodType(Function.class,cls),
type.generic(), mh, type).getTarget();
factory.bindTo(cls.cast(instance));
return (Function) factory.invokeExact(cls.cast(instance));
} catch (Throwable e) {
logger.error("get Function fail, cause :" ,e);
return null;
}
}
Вот исключение:
java.lang.invoke.WrongMethodTypeException: expected (TestService)Function but found (Object)Function
at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:298)
at java.lang.invoke.Invokers.checkExactType(Invokers.java:309)
at com.utils.cache.ClassUtils.generateLambda(ClassUtils.java:182)
Строка 182:
return (Function) factory.invokeExact(cls.cast(instance));
Я знаю, что только статический метод может решить эту проблему, но я хочу знать, есть ли другой способ решить эту проблему, не меняя нестатический на статический.
Вот getInstance:
private static Object getInstance(@NotNull Class<?> cls) {
try {
Method getInstanceMethod = cls.getDeclaredMethod("getInstance");
return getInstanceMethod.invoke(null);
} catch (Exception e) {
logger.error("get instance fail, cause :" ,e);
return null;
}
}
В этом методе я использую рефлексию, чтобы найти статический метод getInstance в классе, и возвращаю экземпляр, это просто простой синглтон.