LambdaReflectUtil
2020-11-23 本文已影响0人
LoWang
package com.test;
import java.beans.Introspector;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import com.google.common.base.CaseFormat;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
public class LambdaReflectUtil {
public static void main(String[] args) {
Student st = new Student();
String fieldName = LambdaReflectUtil.getName(Student::getStudentName);
System.out.println(fieldName);
fieldName = LambdaReflectUtil.getUnderscoreName(Student::getStudentName);
System.out.println(fieldName);
st.setStudentName("张三");
st.setId(201L);
Object obj = BeanParamBuilder.of(st).checkAndBuild(Student::getStudentName).checkAndBuild(Student::getId)
.set("ss.classId", 999L).buildMap();
System.out.println(obj);
obj = BeanParamBuilder.of(st).checkAndBuild(Student::getStudentName).checkAndBuild(Student::getId)
.set("ss.classId", 999L).buildUnderscoreMap();
System.out.println(obj);
}
@RequiredArgsConstructor(staticName = "of")
public static class BeanParamBuilder<T> {
private final T t;
@Setter
private String prefix;
private Map<String, Object> params = new HashMap<>();
public BeanParamBuilder<T> checkAndBuild(TypeFunction<T, ?> fn) {
String name = LambdaReflectUtil.getName(fn);
Field field = ReflectionUtils.findField(t.getClass(), name);
if (Objects.nonNull(field)) {
ReflectionUtils.makeAccessible(field);
Object value = ReflectionUtils.getField(field, t);
if (StringUtils.isNotBlank(prefix)) {
name = String.format("%s_%s", prefix, name);
}
params.put(name, value);
}
return this;
}
public BeanParamBuilder<T> set(String key, Object value) {
key = key.replaceAll("[.]", "_");
params.put(key, value);
return this;
}
public Map<String, Object> buildMap() {
return params;
}
public Map<String, Object> buildUnderscoreMap() {
if (MapUtils.isNotEmpty(params)) {
Map<String, Object> converted = new HashMap<>(params.size());
params.entrySet().stream().forEach(entry -> {
converted.put(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey()),
entry.getValue());
});
return converted;
} else {
return Collections.emptyMap();
}
}
}
public static <T> String getUnderscoreName(SFunction<T, ?> fn) {
// 从function取出序列化方法
Method writeReplaceMethod;
try {
writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
// 从序列化方法取出序列化的lambda信息
boolean isAccessible = writeReplaceMethod.canAccess(fn);
writeReplaceMethod.setAccessible(Boolean.TRUE);
SerializedLambda serializedLambda;
try {
serializedLambda = (SerializedLambda)writeReplaceMethod.invoke(fn);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
writeReplaceMethod.setAccessible(isAccessible);
// 从lambda信息取出method、field、class等
String fieldName = serializedLambda.getImplMethodName().substring("get".length());
fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
return fieldName.replaceAll("[A-Z]", "_$0").toLowerCase();
}
public static <T, R> String getName(TypeFunction<T, R> fn) {
return TypeFunction.getLambdaColumnName(fn);
}
@Data
public static class Student {
private Long id;
private String studentName;
private String studentAge;
}
@FunctionalInterface
public static interface SFunction<T, R> extends Function<T, R>, Serializable {}
@FunctionalInterface
public static interface TypeFunction<T, R> extends Serializable, Function<T, R> {
/**
* 获取列名称
*
* @param lambda
* @return String
*/
static String getLambdaColumnName(Serializable lambda) {
try {
Method method = lambda.getClass().getDeclaredMethod("writeReplace");
method.setAccessible(Boolean.TRUE);
SerializedLambda serializedLambda = (SerializedLambda)method.invoke(lambda);
String getter = serializedLambda.getImplMethodName();
String fieldName = Introspector.decapitalize(getter.replace("get", ""));
return fieldName;
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}
}