Created
June 14, 2018 04:58
-
-
Save kogupta/dc7ee0cd361d6564dab25a2ffebbe343 to your computer and use it in GitHub Desktop.
bean introspection using lambda metafactory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.invoke.LambdaMetafactory; | |
import java.lang.invoke.MethodHandle; | |
import java.lang.invoke.MethodHandles; | |
import java.lang.invoke.MethodType; | |
import java.lang.reflect.Method; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
import java.util.function.Function; | |
/** | |
* Fetch the `get` methods of a bean/pojo. | |
* Same thing can be achieved by bean introspection as well. | |
* | |
* @param <T> | |
*/ | |
public final class PojoGetters<T> { | |
private final Map<String, Function> getters; | |
private PojoGetters(Class<T> clazz) { | |
this.getters = new LinkedHashMap<>(); | |
Method[] methods = clazz.getMethods(); | |
for (Method method : methods) { | |
if (method.getName().startsWith("get")) { | |
getters.put(method.getName(), getter(method)); | |
} | |
} | |
} | |
private static Function getter(Method method) { | |
try { | |
MethodHandles.Lookup caller = MethodHandles.lookup(); | |
MethodHandle handle = caller.unreflect(method); | |
return (Function) LambdaMetafactory.metafactory( | |
caller, | |
"apply", | |
MethodType.methodType(Function.class), | |
MethodType.methodType(Object.class, Object.class), | |
handle, | |
handle.type()) | |
.getTarget() | |
.invoke(); | |
} catch (Throwable e) { | |
throw new RuntimeException("Could not generate the function to access the getter " + method.getName(), e); | |
} | |
} | |
/** | |
* Given field `price` returns method name `getPrice` | |
* | |
* @param fieldName | |
* @return method name of getter corresponding to field | |
*/ | |
private static String getterName(String fieldName) { | |
char oldChar = fieldName.charAt(0); | |
char upperCase = Character.toUpperCase(oldChar); | |
String methodName = "get" + upperCase + fieldName.substring(1); | |
// System.out.println("Method name: " + methodName); | |
return methodName; | |
} | |
public Object invokeByGetter(T instance, String methodName) { | |
Function fn = getters.get(methodName); | |
return fn.apply(instance); | |
} | |
public Object invokeByField(T instance, String field) { | |
return invokeByGetter(instance, getterName(field)); | |
} | |
public static <T> PojoGetters<T> of(Class<T> clazz) { | |
return new PojoGetters<>(clazz); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment