From 0754660c45ff83086462c15048f6fdd3ffd818b6 Mon Sep 17 00:00:00 2001 From: yexuejc007 Date: Tue, 13 Jun 2023 17:55:37 +0800 Subject: [PATCH] =?UTF-8?q?[feat]=20ObjUtil=20=E5=A2=9E=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=9A=84=E6=B7=B1=E5=BA=A6copy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yexuejc/base/util/ObjUtil.java | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/src/main/java/com/yexuejc/base/util/ObjUtil.java b/src/main/java/com/yexuejc/base/util/ObjUtil.java index 51f70fa..d11c9ca 100644 --- a/src/main/java/com/yexuejc/base/util/ObjUtil.java +++ b/src/main/java/com/yexuejc/base/util/ObjUtil.java @@ -4,9 +4,11 @@ import com.yexuejc.base.annotation.ToUeProperty; import java.io.*; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; /** * 对象工具:对类的操作 @@ -260,4 +262,145 @@ public class ObjUtil { return outer; } + /** + * 复制对象属性值,包含父类 (不需要getter和setter) + *

includeField和excludeField同时传入,走包含逻辑,

+ * + * @param source 源对象 + * @param targetClass 目标对象class + * @param includeField 包含对象 + * @param excludeField 排除对象 + * @param + * @param + * @return 目标对象 + * @throws Exception + */ + public static O copy(I source, Class targetClass, List includeField, List excludeField) throws Exception { + List allFields = getAllFields(source.getClass()); + O o = targetClass.getDeclaredConstructor().newInstance(); + if (StrUtil.isNotEmpty(excludeField) && StrUtil.isEmpty(includeField)) { + allFields = allFields.stream().filter(f -> !excludeField.contains(f.getName())).collect(Collectors.toList()); + } + if (StrUtil.isNotEmpty(includeField)) { + allFields = allFields.stream().filter(f -> includeField.contains(f.getName())).collect(Collectors.toList()); + } + allFields.forEach(f -> { + try { + try { + Field field = targetClass.getDeclaredField(f.getName()); + if (field != null) { + f.setAccessible(true); + Object v = f.get(source); + f.setAccessible(false); + field.setAccessible(true); + field.set(o, v); + field.setAccessible(false); + } + } catch (NoSuchFieldException e) { + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + return o; + } + + /** + * 深度复制对象 + *

获取source的所有getXxx。xxx作为属性,且包含父类的getXxx

+ *

查找target的xxx属性,进行反射设值

+ * + * @param source 源对象 + * @param targetClass 目标对象class + * @param invokeSetter 设置target属性值时,是否使用setter方法设置 + * @param + * @param + * @return 目标对象 + */ + public static O copy(I source, Class targetClass, boolean invokeSetter) throws Exception { + List getterMethods = getAllGetterMethods(source.getClass(), "get"); + O o = targetClass.getDeclaredConstructor().newInstance(); + getterMethods.forEach(method -> { + try { + String fieldName = method.getName().replace("get", ""); + Object v = method.invoke(source); + if (invokeSetter) { + try { + Method setterMethod = targetClass.getDeclaredMethod("set" + fieldName, method.getReturnType()); + if (null != setterMethod) { + setterMethod.invoke(o, v); + } + } catch (NoSuchMethodException e) { + } + } else { + try { + Field field = targetClass.getDeclaredField(lowerCaseFirstChar(fieldName)); + if (field != null) { + field.setAccessible(true); + field.set(o, v); + field.setAccessible(false); + } + } catch (NoSuchFieldException e) { + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + return o; + } + + /** + * 获取所有方法,包含父类 + * + * @param beanClass + * @param startsWith 方法的开头匹配(空,返回所有) + * @return + */ + public static List getAllGetterMethods(Class beanClass, String startsWith) { + List methodList = new ArrayList<>(); + Method[] methods = beanClass.getDeclaredMethods(); + if (StrUtil.isNotEmpty(startsWith)) { + methodList.addAll(Arrays.stream(methods) + .filter(method -> method.getName().startsWith(startsWith)) + .collect(Collectors.toList())); + } else { + methodList.addAll(Arrays.asList(methods)); + } + Class superclass = beanClass.getSuperclass(); + if (superclass != null) { + methodList.addAll(getAllGetterMethods(superclass, startsWith)); + } + return methodList; + } + + /** + * 获取所有属性,包含父类 + * + * @param beanClass + * @return + */ + public static List getAllFields(Class beanClass) { + List fieldList = new ArrayList<>(); + while (beanClass != null) { + fieldList.addAll(Arrays.asList(beanClass.getDeclaredFields())); + beanClass = beanClass.getSuperclass(); + } + return fieldList; + } + + /** + * 首字母小写 + * + * @param str + * @return + */ + public static String lowerCaseFirstChar(String str) { + if (str == null || str.length() == 0) { + return str; + } else { + return str.substring(0, 1).toLowerCase() + str.substring(1); + } + } + }