使用过 mybatis-plus 都知道其可以使用jdk8中引入的方法引用动态获取对象属性的字段名称,从而解决了硬编码的问题!我们也可以简单的实现一下
一、新建一个函数式接口
/**
* @author wfd
* @description
* @create 2021/5/2 0:17
*/
@FunctionalInterface
public interface DynamicFieldFunction<T,R> extends Function<T, R>, Serializable {
}
二、新建一个 DynamicField 类,具体实现如何获取名称
package com.wfd.study.func;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author wfd
* @description
* @create 2021/5/2 0:19
*/
public class DynamicField {
public static final String PREFIX_GET = "get";
public static final String PREFIX_IS = "is";
private static Logger log = LoggerFactory.getLogger(DynamicField.class);
/**
* 获取驼峰式的字段名
* @param dynamicField
* @param <T>
* @param <R>
* @return
*/
public static <T, R> String getFieldColumn(DynamicFieldFunction<T, R> dynamicField) {
// 直接调用writeReplace
Method writeReplace = null;
String methodName = null;
try {
writeReplace = dynamicField.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
Object sl = writeReplace.invoke(dynamicField);
SerializedLambda serializedLambda = (SerializedLambda) sl;
methodName = serializedLambda.getImplMethodName();
if (methodName.startsWith(PREFIX_GET)) {
methodName = methodName.substring(PREFIX_GET.length());
} else if (methodName.startsWith(PREFIX_IS)) {
methodName = methodName.substring(PREFIX_IS.length());
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
log.error("动态获取属性名称失败:{}", e.getMessage());
return "";
}
return firstToLowerCase(methodName);
}
/**
* 将驼峰式名称转为下划线命名,主要用于Map集合中根据key获取值,也可解决硬编码的问题
* @param dynamicField
* @param <T>
* @param <R>
* @return
*/
public static <T, R> String getFieldUnderline(DynamicFieldFunction<T, R> dynamicField) {
// 直接调用writeReplace
Method writeReplace = null;
String methodName = null;
try {
writeReplace = dynamicField.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
Object sl = writeReplace.invoke(dynamicField);
SerializedLambda serializedLambda = (SerializedLambda) sl;
methodName = serializedLambda.getImplMethodName();
if (methodName.startsWith(PREFIX_GET)) {
methodName = methodName.substring(PREFIX_GET.length());
} else if (methodName.startsWith(PREFIX_IS)) {
methodName = methodName.substring(PREFIX_IS.length());
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
log.error("动态获取属性名称失败:{}", e.getMessage());
return "";
}
return camelToUnderline(methodName);
}
public static String camelToUnderline(String camelString){
if (null == camelString || "".equals(camelString)) {
return camelString;
}
camelString = String.valueOf(camelString.charAt(0)).toUpperCase().concat(camelString.substring(1));
StringBuilder sb = new StringBuilder();
Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
Matcher matcher = pattern.matcher(camelString);
while (matcher.find()) {
String word = matcher.group();
sb.append(word.toLowerCase());
sb.append(matcher.end() == camelString.length() ? "" : "_");
}
return sb.toString();
}
private static String firstToLowerCase(String s) {
if (Character.isLowerCase(s.charAt(0)))
return s;
else
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
}
三、测试
public class Test {
public static void main(String[] args) throws Exception {
String fieldColumn = DynamicField.getFieldColumn(Spu::getName);
// 输出 name
System.out.println("fieldColumn = " + fieldColumn);
}
}