diff --git a/src/main/java/com/zhgd/xmgl/util/ReflectionUtil.java b/src/main/java/com/zhgd/xmgl/util/ReflectionUtil.java new file mode 100644 index 000000000..10bbbf401 --- /dev/null +++ b/src/main/java/com/zhgd/xmgl/util/ReflectionUtil.java @@ -0,0 +1,74 @@ +package com.zhgd.xmgl.util; + +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +import java.beans.Introspector; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 方法引用获取属性名工具类 + */ +public class ReflectionUtil { + + private static Map, Field> cache = new ConcurrentHashMap<>(); + + /** + * 方法引用获取属性名 + * + * @param function + * @param + * @param + * @return + */ + public static String getFieldName(SerializableFunction function) { + Field field = ReflectionUtil.getField(function); + return field.getName(); + } + + public static Field getField(SerializableFunction function) { + return cache.computeIfAbsent(function, ReflectionUtil::findField); + } + + public static Field findField(SerializableFunction function) { + Field field = null; + String fieldName = null; + try { + // 第1步 获取SerializedLambda + Method method = function.getClass().getDeclaredMethod("writeReplace"); + method.setAccessible(Boolean.TRUE); + SerializedLambda serializedLambda = (SerializedLambda) method.invoke(function); + // 第2步 implMethodName 即为Field对应的Getter方法名 + String implMethodName = serializedLambda.getImplMethodName(); + if (implMethodName.startsWith("get") && implMethodName.length() > 3) { + fieldName = Introspector.decapitalize(implMethodName.substring(3)); + + } else if (implMethodName.startsWith("is") && implMethodName.length() > 2) { + fieldName = Introspector.decapitalize(implMethodName.substring(2)); + } else if (implMethodName.startsWith("lambda$")) { + throw new IllegalArgumentException("SerializableFunction不能传递lambda表达式,只能使用方法引用"); + + } else { + throw new IllegalArgumentException(implMethodName + "不是Getter方法引用"); + } + // 第3步 获取的Class是字符串,并且包名是“/”分割,需要替换成“.”,才能获取到对应的Class对象 + String declaredClass = serializedLambda.getImplClass().replace("/", "."); + Class aClass = Class.forName(declaredClass, false, ClassUtils.getDefaultClassLoader()); + + // 第4步 Spring 中的反射工具类获取Class中定义的Field + field = ReflectionUtils.findField(aClass, fieldName); + + } catch (Exception e) { + e.printStackTrace(); + } + // 第5步 如果没有找到对应的字段应该抛出异常 + if (field != null) { + return field; + } + throw new NoSuchFieldError(fieldName); + } +} diff --git a/src/main/java/com/zhgd/xmgl/util/SerializableFunction.java b/src/main/java/com/zhgd/xmgl/util/SerializableFunction.java new file mode 100644 index 000000000..38c5ce9cc --- /dev/null +++ b/src/main/java/com/zhgd/xmgl/util/SerializableFunction.java @@ -0,0 +1,9 @@ +package com.zhgd.xmgl.util; + +import java.io.Serializable; +import java.util.function.Function; + +@FunctionalInterface +public interface SerializableFunction extends Function, Serializable { + +}