import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanMap;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Bean 工具类
*/
@Slf4j
public class BeanUtils extends org.springframework.beans.BeanUtils {
/**
* Bean方法名中属性名开始的下标
*/
private static final int BEAN_METHOD_PROP_INDEX = 3;
/**
* 匹配getter方法的正则表达式
*/
private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
/**
* 匹配setter方法的正则表达式
*/
private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
/**
* get方法前缀
*/
private static final String GET = "get";
/**
* set方法前缀
*/
private static final String SET = "set";
/**
* 隐藏方法“writeReplace”
*/
private static final String WRITE_REPLACE = "writeReplace";
/**
* copy时自动过滤某些字段
*/
private static final List<String> ignoreFields = Arrays.asList("createTime", "createUser", "updateTime", "updateUser", "status", "deleted");
/**
* Bean属性复制工具方法。
*
* @param dest 目标对象
* @param src 源对象
*/
public static void copyBeanProp(Object dest, Object src) {
try {
copyProperties(src, dest);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对象的setter方法。
*
* @param obj 对象
* @return 对象的setter方法列表
*/
public static List<Method> getSetterMethods(Object obj) {
// setter方法列表
List<Method> setterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找setter方法
for (Method method : methods) {
Matcher m = SET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 1)) {
setterMethods.add(method);
}
}
// 返回setter方法列表
return setterMethods;
}
/**
* 获取对象的getter方法。
*
* @param obj 对象
* @return 对象的getter方法列表
*/
public static List<Method> getGetterMethods(Object obj) {
// getter方法列表
List<Method> getterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找getter方法
for (Method method : methods) {
Matcher m = GET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 0)) {
getterMethods.add(method);
}
}
// 返回getter方法列表
return getterMethods;
}
/**
* 检查Bean方法名中的属性名是否相等。<br>
* 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。
*
* @param m1 方法名1
* @param m2 方法名2
* @return 属性名一样返回true,否则返回false
*/
public static boolean isMethodPropEquals(String m1, String m2) {
return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
}
/**
* 集合数据的拷贝 * @param sources: 数据源类 * @param target: 目标类::new(eg: UserVO::new) * @return
*/
public static <S, T> List<T> copyListProperties(Collection<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
* 带回调函数的集合数据的拷贝(可自定义字段拷贝规则) * @param sources: 数据源类 * @param target: 目标类::new(eg: UserVO::new) * @param callBack: 回调函数 * @return
*/
public static <S, T> List<T> copyListProperties(Collection<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
copyProperties(source, t);
list.add(t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
}
return list;
}
/**
* bean复制忽略某些字段 target::new
*
* @param source
* @param target
* @param <T>
* @return
*/
public static <T, R> void copyProperties(Object source, Object target, BeanFunction<T, R>... ignoreFunction) {
if (Objects.nonNull(ignoreFunction)) {
List<String> ignoreFunctionList = Arrays.stream(ignoreFunction).map(ignore -> getFieldName(ignore)).collect(Collectors.toList());
ignoreFunctionList.addAll(ignoreFields);
copyProperties(source, target, ignoreFunctionList.toArray(new String[ignoreFunctionList.size()]));
}
}
/**
* 复制后的新对象可进行修改操作,主要用于两个对象存在不同名称的属性,但是值确实相同时
* 如:target对象的patientId需要取 source对象的id, e -> e.setPatientId(source.getId)
* @param source
* @param target
* @param consumer
* @param <T>
* @param <R>
*/
public static <T, R> void copyProperty(T source, R target, Consumer<R> consumer) {
copyProperties(source, target);
consumer.accept(target);
}
/**
* bean复制忽略某些字段 target::new
*
* @param source
* @param target
* @param <S>
* @param <T>
* @return
*/
public static <S, T, R> T copyProperties(S source, Supplier<T> target, BeanFunction<T, R>... ignoreFunction) {
T t = target.get();
if (Objects.nonNull(ignoreFunction)) {
List<String> ignoreFunctionList = Arrays.stream(ignoreFunction).map(ignore -> getFieldName(ignore)).collect(Collectors.toList());
ignoreFunctionList.addAll(ignoreFields);
copyProperties(source, t, ignoreFunctionList.toArray(new String[ignoreFunctionList.size()]));
}
return t;
}
/**
* 集合复制忽略某些字段
*
* @param sources
* @param target
* @param callBack
* @param <S>
* @param <T>
* @return
*/
public static <S, T, R> List<T> copyListProperties(Collection<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack, BeanFunction<T, R>... ignoreFunction) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
if (Objects.nonNull(ignoreFunction)) {
List<String> ignoreFunctionList = Arrays.stream(ignoreFunction).map(ignore -> getFieldName(ignore)).collect(Collectors.toList());
ignoreFunctionList.addAll(ignoreFields);
copyProperties(source, t, ignoreFunctionList.toArray(new String[ignoreFunctionList.size()]));
}
list.add(t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
}
return list;
}
/**
* 集合复制忽略某些字段
*
* @param sources
* @param targetFunc
* @param callBack
* @param <S>
* @param <T>
* @return
*/
public static <S, T, R, U, V> List<T> copyListProperties(Collection<S> sources, Function<S,T> targetFunc, BeanCopyUtilCallBack<S, T> callBack, BeanFunction<T, R>... ignoreFunction) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = targetFunc.apply(source);
if (Objects.nonNull(ignoreFunction)) {
List<String> ignoreFunctionList = Arrays.stream(ignoreFunction).map(ignore -> getFieldName(ignore)).collect(Collectors.toList());
ignoreFunctionList.addAll(ignoreFields);
copyProperties(source, t, ignoreFunctionList.toArray(new String[ignoreFunctionList.size()]));
}
list.add(t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
}
return list;
}
/**
* map转实体类
*
* @param map
* @param clazz
* @param <T>
* @return
*/
public static <T> T mapToBean(HashMap map, Class<T> clazz) {
return JSON.parseObject(JSON.toJSONString(map), clazz);
}
/**
* 实体类转map
*
* @param bean
* @param <T>
* @return
*/
public static <T> Map<String, ?> beanToMap(T bean) {
if (bean instanceof Map) {
return (Map) bean;
}
BeanMap beanMap = BeanMap.create(bean);
Map<String, Object> map = new HashMap<>();
beanMap.forEach((key, value) -> {
map.put(String.valueOf(key), value);
});
return map;
}
// 拿到getter方法对应的属性名称
public static <T> String getFieldName(BeanFunction<T, ?> field) {
Class<?> clazz = field.getClass();
try {
Method method = clazz.getDeclaredMethod(WRITE_REPLACE);
method.setAccessible(true);
SerializedLambda lambda = (SerializedLambda) method.invoke(field);
String fieldName = lambda.getImplMethodName().substring("get".length());
return toLowerCaseFirstOne(fieldName);
} catch (Exception e) {
if (!Object.class.isAssignableFrom(clazz.getSuperclass())) {
return getFieldName(field);
}
throw new RuntimeException("current property is not exists");
}
}
/**
* 字符串首字母转小写
*/
public static String toLowerCaseFirstOne(String field) {
if (Character.isLowerCase(field.charAt(0))) {
return field;
} else {
char firstOne = Character.toLowerCase(field.charAt(0));
String other = field.substring(1);
return new StringBuilder().append(firstOne).append(other).toString();
}
}
/**
* List<object> 转换为List<实体类>
* @param list
* @param clazz
* @param <T>
* @return
*/
public static <T> List<T> changeClazzList(List list, Class<T> clazz) {
return (List<T>) list.stream().map(obj -> JSON.parseObject(JSON.toJSONString(obj),clazz)).collect(Collectors.toList());
}
}
Java Bean 工具类
于 2024-04-10 09:36:39 首次发布