wisdomisite-java/src/main/java/com/zhgd/xmgl/util/ReflectionUtil.java

116 lines
4.1 KiB
Java
Raw Normal View History

package com.zhgd.xmgl.util;
import cn.hutool.core.util.StrUtil;
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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 方法引用获取属性名工具类
*/
public class ReflectionUtil {
private static Map<SerializableFunction<?, ?>, Field> cache = new ConcurrentHashMap<>();
2023-05-24 11:34:44 +08:00
/**
* 获取字段名列表前面拼上别名别名.属性名
*
* @param alias
* @param functions
* @param <T>
* @param <R>
* @return
*/
public static <T, R> List<String> getFieldNameList(String alias, SerializableFunction<T, R>... functions) {
return Arrays.stream(functions).map(function -> alias + "." + getFieldName(function)).collect(Collectors.toList());
}
2023-05-24 11:34:44 +08:00
/**
* 获取字段名列表
*
* @param functions
* @param <T>
* @param <R>
* @return
*/
public static <T, R> List<String> getFieldNameList(SerializableFunction<T, R>... functions) {
return Arrays.stream(functions).map(ReflectionUtil::getFieldName).collect(Collectors.toList());
2023-04-24 17:42:24 +08:00
}
2023-05-24 11:34:44 +08:00
/**
* 方法引用获取属性名并转成下划线
*
* @param function
* @param <T>
* @param <R>
* @return
*/
public static <T, R> String getFieldNameToUlc(SerializableFunction<T, R> function) {
return StrUtil.toUnderlineCase(getFieldName(function));
}
/**
* 方法引用获取属性名
*
* @param function
* @param <T>
* @param <R>
* @return
*/
public static <T, R> String getFieldName(SerializableFunction<T, R> function) {
Field field = ReflectionUtil.getField(function);
return field.getName();
}
2023-05-24 11:34:44 +08:00
private static <T, R> Field getField(SerializableFunction<T, R> function) {
return cache.computeIfAbsent(function, ReflectionUtil::findField);
}
2023-05-24 11:34:44 +08:00
private static <T, R> Field findField(SerializableFunction<T, R> 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);
}
}