All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diboot.core.util.BeanUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015-2020, www.dibo.ltd ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.diboot.core.util; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.diboot.core.config.Cons; import com.diboot.core.converter.EnhancedConversionService; import com.diboot.core.data.copy.AcceptAnnoCopier; import com.diboot.core.entity.BaseEntity; import com.diboot.core.exception.BusinessException; import com.diboot.core.vo.LabelValue; import com.diboot.core.vo.Status; import org.apache.commons.lang3.ArrayUtils; import org.apache.ibatis.reflection.property.PropertyNamer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.beans.BeanWrapper; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.core.ResolvableType; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.util.ReflectionUtils; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.invoke.SerializedLambda; import java.lang.reflect.*; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; /** * Bean相关处理工具类 * @author [email protected] * @version v2.0 * @date 2019/01/01 */ @SuppressWarnings({"unchecked", "rawtypes", "JavaDoc", "unused"}) public class BeanUtils { private static final Logger log = LoggerFactory.getLogger(BeanUtils.class); /** * 连接符号 */ private static final String CHANGE_FLAG = "->"; /** * 忽略对比的字段 */ private static final Set IGNORE_FIELDS = new HashSet(){{ add(Cons.FieldName.createTime.name()); }}; /** * Copy属性到另一个对象 * @param source * @param target */ @SuppressWarnings("UnusedReturnValue") public static T copyProperties(Object source, T target){ // 链式调用无法使用BeanCopier拷贝,换用BeanUtils org.springframework.beans.BeanUtils.copyProperties(source, target); // 处理Accept注解标识的不同字段名拷贝 AcceptAnnoCopier.copyAcceptProperties(source, target); return target; } /** * 将对象转换为另外的对象实例 * @param source * @param clazz * @param * @return */ public static T convert(Object source, Class clazz){ if(source == null){ return null; } T target = null; try{ target = clazz.getConstructor().newInstance(); copyProperties(source, target); } catch (Exception e){ log.warn("对象转换异常, class={}", clazz.getName()); } return target; } /** * 将对象转换为另外的对象实例 * @param sourceList * @param clazz * @param * @return */ @SuppressWarnings("unchecked") public static List convertList(List sourceList, Class clazz) { if(V.isEmpty(sourceList)){ return Collections.emptyList(); } // 类型相同,直接跳过 if (clazz.equals(sourceList.get(0).getClass())) { return (List) sourceList; } // 不同,则转换 List resultList = new ArrayList<>(sourceList.size()); try{ for(Object source : sourceList){ T target = clazz.getConstructor().newInstance(); copyProperties(source, target); resultList.add(target); } } catch (Exception e){ log.error("对象转换异常, class: {}, error: {}", clazz.getName(), e.getMessage()); return Collections.emptyList(); } return resultList; } /** * 构建Map为Bean * @param dataMap * @param entityClass * @return * @param */ public static T convertMap2Bean(Map dataMap, Class entityClass) { // 字段映射 if(V.isEmpty(dataMap)){ return null; } T entityInstance = null; try { entityInstance = entityClass.getConstructor().newInstance(); } catch (Exception e){ log.warn("实例化Bean {} 异常: {}", entityClass.getSimpleName(), e.getMessage()); } bindProperties(entityInstance, dataMap); return entityInstance; } /** * 构建MapList为Bean列表 * @param resultListMap * @param entityClass * @return * @param */ public static List convertMap2BeanList(List> resultListMap, Class entityClass) { if(V.isEmpty(resultListMap)){ return Collections.emptyList(); } List entityList = new ArrayList<>(resultListMap.size()); for(Map resultMap : resultListMap){ T entityInstance = convertMap2Bean(resultMap, entityClass); if(entityInstance != null) { entityList.add(entityInstance); } } return entityList; } /** * 附加Map中的属性值到Model * @param model * @param propMap */ public static void bindProperties(Object model, Map propMap){ if (V.isAnyEmpty(model, propMap)) { return; } BeanWrapper beanWrapper = getBeanWrapper(model); for(Map.Entry entry : propMap.entrySet()){ try{ beanWrapper.setPropertyValue(entry.getKey(), entry.getValue()); } catch (Exception e){ log.debug("复制属性{}.{}异常: {}", model.getClass().getSimpleName(), entry.getKey(), e.getMessage()); } } } /** * 获取对象的属性值 * @param obj * @param field * @return */ public static Object getProperty(Object obj, String field){ if(field == null) { return null; } if(obj instanceof Map){ Map objMap = (Map)obj; return objMap.get(field); } try { BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(obj); return wrapper.getPropertyValue(field); } catch (Exception e) { log.warn("获取对象属性值出错,返回null", e); } return null; } /** * 获取对象的属性值并转换为String * @param obj * @param field * @return */ public static String getStringProperty(Object obj, String field){ Object property = getProperty(obj, field); if(property == null){ return null; } return String.valueOf(property); } /** * 设置属性值 * @param obj */ private static ConversionService conversionService; public synchronized static BeanWrapper getBeanWrapper(Object obj) { BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(obj); if(conversionService == null) { conversionService = ContextHolder.getBean(DefaultConversionService.class); if(conversionService == null) { List converterList = ContextHolder.getBeans(Converter.class); conversionService = new EnhancedConversionService(converterList); log.debug("new ConversionService instance: {}", EnhancedConversionService.class.getName()); } else { log.debug("get ConversionService instance: {} by getBean", conversionService.getClass().getName()); } } wrapper.setConversionService(conversionService); return wrapper; } /** * 设置属性值 * @param obj * @param field * @param value */ public static void setProperty(Object obj, String field, Object value) { BeanWrapper wrapper = getBeanWrapper(obj); wrapper.setPropertyValue(field, value); } /** * 类型class对象-转换方法 */ private static final Map, Function> fieldConverterMap = new HashMap, Function>() {{ put(Integer.class, Integer::parseInt); put(Long.class, Long::parseLong); put(Double.class, Double::parseDouble); put(BigDecimal.class, BigDecimal::new); put(Float.class, Float::parseFloat); put(Boolean.class, V::isTrue); put(Date.class, D::fuzzyConvert); }}; /** * 转换为field对应的类型 * @param value * @param field * @return */ public static Object convertValueToFieldType(Object value, Field field){ if(value == null){ return null; } return convertValueToFieldType(value, field.getType()); } /** * 转换为field对应的类型 * @param value * @param fieldType * @return */ public static Object convertValueToFieldType(Object value, Class fieldType){ if(value == null){ return null; } if (value.getClass().equals(fieldType)) { return value; } String valueStr = S.valueOf(value); if (fieldConverterMap.containsKey(fieldType)) { return fieldConverterMap.get(fieldType).apply(valueStr); } else if (LocalDate.class.equals(fieldType) || LocalDateTime.class.equals(fieldType)) { Date dateVal = (value instanceof Date) ? (Date) value : D.fuzzyConvert(valueStr); if (dateVal == null) { return null; } ZonedDateTime zonedDateTime = dateVal.toInstant().atZone(ZoneId.systemDefault()); return LocalDateTime.class.equals(fieldType) ? zonedDateTime.toLocalDateTime() : zonedDateTime.toLocalDate(); } else if (Serializable.class.isAssignableFrom(fieldType)) { if(value instanceof String) { return valueStr; } return JSON.parseObject(valueStr, fieldType); } return value; } /** * Key-Object对象Map * @param allLists * @param getterFns * @return */ public static Map convertToStringKeyObjectMap(List allLists, IGetter... getterFns){ String[] fields = convertGettersToFields(getterFns); return convertToStringKeyObjectMap(allLists, fields); } /** * Key-Object对象Map * @param allLists * @param fields * @return */ public static Map convertToStringKeyObjectMap(List allLists, String... fields){ if(allLists == null || allLists.isEmpty()){ return Collections.EMPTY_MAP; } Map allListMap = new LinkedHashMap<>(allLists.size()); ModelKeyGenerator keyGenerator = new ModelKeyGenerator(fields); // 转换为map try { for (T model : allLists) { String key = keyGenerator.generate(model); if (key != null) { allListMap.put(key, model); } else{ log.warn("{} 的属性 {} 值存在 null,转换结果需要确认!", model.getClass().getName(), fields[0]); } } } catch(Exception e){ log.warn("转换key-model异常", e); } return allListMap; } /** * Key-Object对象Map * @param allLists * @param getterFns * @return */ public static Map> convertToStringKeyObjectListMap(List allLists, IGetter... getterFns){ String[] fields = convertGettersToFields(getterFns); return convertToStringKeyObjectListMap(allLists, fields); } /** * Key-Object-List列表Map * @param allLists * @param fields * @param * @return */ public static Map> convertToStringKeyObjectListMap(List allLists, String... fields){ if (V.isEmpty(allLists)) { return Collections.emptyMap(); } Map> allListMap = new LinkedHashMap<>(allLists.size()); ModelKeyGenerator keyGenerator = new ModelKeyGenerator(fields); // 转换为map try { for (T model : allLists) { String key = keyGenerator.generate(model); if(key != null){ List list = allListMap.computeIfAbsent(key, k -> new ArrayList<>()); list.add(model); } else{ log.warn("{} 的属性 {} 值存在 null,转换结果需要确认!", model.getClass().getName(), fields[0]); } } } catch (Exception e){ log.warn("转换key-model-list异常", e); } return allListMap; } /** * key生成器,按照传入的fields字段列表给指定对象生成key */ private static class ModelKeyGenerator { private final String[] fields; /** * fields是否为空 */ private final boolean isFieldsEmpty; /** * fields是否只有一个元素 */ private final boolean isFieldsOnlyOne; public ModelKeyGenerator(String[] fields) { this.fields = fields; isFieldsEmpty = V.isEmpty(fields); isFieldsOnlyOne = !isFieldsEmpty && fields.length == 1; } /** * 从model中提取指定字段生成key,如果为指定字段则默认为id字段 * 不建议大量数据循环时调用 * * @param model 提取对象 * @return model中字段生成的key */ public String generate(Object model) { String key = null; if (isFieldsEmpty) { //未指定字段,以id为key return getStringProperty(model, Cons.FieldName.id.name()); } // 指定了一个字段,以该字段为key,类型同该字段 else if (isFieldsOnlyOne) { return getStringProperty(model, fields[0]); } else { // 指定了多个字段,以字段S.join的结果为key,类型为String List list = new ArrayList(fields.length); for (String field : fields) { list.add(getProperty(model, field)); } return S.join(list); } } } /** * 构建指定根节点的上下级关联的树形结构(主键id,上级属性parentId、子节点属性children) * * @param allNodes 所有节点对象 * @param * @return */ public static List buildTree(List allNodes) { return buildTree(allNodes, null); } /** * 构建指定根节点的上下级关联的树形结构(主键id,上级属性parentId、子节点属性children) * * @param allNodes 所有节点对象 * @param rootNodeId 跟节点ID * @param * @return */ public static List buildTree(List allNodes, Object rootNodeId) { return buildTree(allNodes, rootNodeId, Cons.FieldName.id.name()); } /** * 构建指定根节点的上下级关联的树形结构(主键指定,上级属性parentId、子节点属性children) * * @param allNodes 所有节点对象 * @param rootNodeId 根节点ID * @param idFieldName 主键属性名 * @param * @return */ public static List buildTree(List allNodes, Object rootNodeId, String idFieldName) { return buildTree(allNodes, rootNodeId, idFieldName, Cons.FieldName.parentId.name(), Cons.FieldName.children.name()); } /** * 构建指定根节点的上下级关联的树形结构(指定主键属性,上级属性、子节点属性名) * * @param allNodes 所有节点对象 * @param rootNodeId 根节点ID * @param idFieldName 主键属性名 * @param parentIdFieldName 父节点属性名 * @param childrenFieldName 子节点集合属性名 * @param * @return */ public static List buildTree(List allNodes, Object rootNodeId, String idFieldName, String parentIdFieldName, String childrenFieldName) { if (V.isEmpty(allNodes)) { return Collections.emptyList(); } Map> parentId2ListMap = new HashMap<>(); // 提取所有的top level对象 for (T node : allNodes) { Object parentId = getProperty(node, parentIdFieldName); Object nodeId = getProperty(node, idFieldName); if (V.equals(nodeId, parentId)) { throw new BusinessException(Status.WARN_PERFORMANCE_ISSUE, "parentId关联自身,请检查!" + node.getClass().getSimpleName() + ":" + nodeId); } parentId2ListMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node); } if (parentId2ListMap.containsKey(rootNodeId)) { return buildTree(parentId2ListMap.remove(rootNodeId), parentId2ListMap, idFieldName, childrenFieldName); } else if (rootNodeId != null) { return Collections.emptyList(); } for (Object parentId : new HashSet<>(parentId2ListMap.keySet())) { if (parentId2ListMap.containsKey(parentId)) { buildTree(parentId2ListMap.get(parentId), parentId2ListMap, idFieldName, childrenFieldName); } } if (parentId2ListMap.size() == 1) { return parentId2ListMap.values().iterator().next(); } log.warn("buildTree根节点ParentId不唯一: {}", parentId2ListMap.values()); throw new BusinessException("exception.business.beanUtils.buildTree.rootParentIdNotUnique"); } /** * 构建tree结构数据 * * @param nodes 顶级节点数据列表 * @param parentId2ListMap 父ID与子元素列表映射 * @param idFieldName ID属性名 * @param childrenFieldName children属性名 * @param 节点类型 * @return 构建Tree结构完成的数据列表 */ public static List buildTree(List nodes, Map> parentId2ListMap, String idFieldName, String childrenFieldName) { for (T item : nodes) { Object id = getProperty(item, idFieldName); if (parentId2ListMap.containsKey(id)) { setProperty(item, childrenFieldName, buildTree(parentId2ListMap.remove(id), parentId2ListMap, idFieldName, childrenFieldName)); } } return nodes; } /** * 构建tree结构数据 * (可不指定根节点ID,但需保证根节点ParentId唯一) * * @param allNodes 数据列表 * @param getId 获取ID方法 * @param getParentId 获取ParentId方法 * @param setChildren 设置Children方法 * @param 节点类型 * @return Tree结构数据 */ public static List buildTree(List allNodes, Function getId, Function getParentId, BiConsumer> setChildren) { return buildTree(allNodes, null, getId, getParentId, setChildren); } /** * 构建tree结构数据 * * @param allNodes 数据列表 * @param rootNodeId 顶级节点Id * @param getId 获取ID方法 * @param getParentId 获取ParentId方法 * @param setChildren 设置Children方法 * @param 节点类型 * @return Tree结构数据 */ public static List buildTree(List allNodes, Serializable rootNodeId, Function getId, Function getParentId, BiConsumer> setChildren) { if (V.isEmpty(allNodes)) { return Collections.emptyList(); } Map> parentId2ListMap = new HashMap<>(); for (T node : allNodes) { Object nodeId = getId.apply(node); Object parentId = getParentId.apply(node); if (V.equals(nodeId, parentId)) { throw new BusinessException(Status.WARN_PERFORMANCE_ISSUE, "exception.business.beanUtils.buildTree.bindSelf", node.getClass().getSimpleName(), nodeId); } parentId2ListMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node); } if (parentId2ListMap.containsKey(rootNodeId)) { return buildTree(parentId2ListMap.remove(rootNodeId), parentId2ListMap, getId, setChildren); } else if (rootNodeId != null) { return Collections.emptyList(); } for (Object parentId : new HashSet<>(parentId2ListMap.keySet())) { if (parentId2ListMap.containsKey(parentId)) { buildTree(parentId2ListMap.get(parentId), parentId2ListMap, getId, setChildren); } } if (parentId2ListMap.size() == 1) { return parentId2ListMap.values().iterator().next(); } throw new BusinessException("buildTree根节点ParentId不唯一"); } /** * 构建tree结构数据 * * @param nodes 顶级节点数据列表 * @param parentId2ListMap 父ID与子元素列表映射 * @param getId 获取ID方法 * @param setChildren 设置Children方法 * @param 节点类型 * @return 构建Tree结构完成的数据列表 */ public static List buildTree(List nodes, Map> parentId2ListMap, Function getId, BiConsumer> setChildren) { for (T item : nodes) { Object id = getId.apply(item); if (parentId2ListMap.containsKey(id)) { setChildren.accept(item, buildTree(parentId2ListMap.remove(id), parentId2ListMap, getId, setChildren)); } } return nodes; } /** * 提取两个model的差异值 * @param oldModel * @param newModel * @return */ public static String extractDiff(BaseEntity oldModel, BaseEntity newModel){ return extractDiff(oldModel, newModel, null); } /** * 提取两个model的差异值,只对比指定字段 * 使用默认的忽略字段 * * @param oldModel * @param newModel * @param fields 对比字段 * @return */ public static String extractDiff(BaseEntity oldModel, BaseEntity newModel, Set fields) { return extractDiff(oldModel, newModel, fields, IGNORE_FIELDS); } /** * 提取两个model的差异值,只对比指定字段 * @param oldModel * @param newModel * @param fields 对比字段 * @param ignoreFields 不对比的字段 * @return */ public static String extractDiff(BaseEntity oldModel, BaseEntity newModel, Set fields, Set ignoreFields) { if(newModel == null || oldModel == null){ log.warn("调用错误,Model不能为空!"); return null; } Map oldMap = oldModel.toMap(); Map newMap = newModel.toMap(); Map result = new HashMap<>(oldMap.size()+newMap.size()); for(Map.Entry entry : oldMap.entrySet()) { String key = entry.getKey(); if (ignoreFields.contains(key)) { continue; } String oldValue = S.defaultValueOf(entry.getValue()); Object newValueObj = newMap.get(key); String newValue = S.defaultValueOf(newValueObj); // 设置变更的值 boolean checkThisField = fields == null || fields.contains(key); if (checkThisField && !oldValue.equals(newValue)) { result.put(key, S.join(oldValue, CHANGE_FLAG, newValue)); } // 从新的map中移除该key if (newValueObj != null) { newMap.remove(key); } } if(!newMap.isEmpty()){ for(Map.Entry entry : newMap.entrySet()) { String key = entry.getKey(); if (ignoreFields.contains(key)) { continue; } String newValue = S.defaultValueOf(entry.getValue()); // 设置变更的值 if (fields == null || fields.contains(key)) { result.put(key, S.join("", CHANGE_FLAG, newValue)); } } } // 转换结果为String return JSON.toJSONString(result); } /** * 从list对象列表中提取指定属性值到新的List * @param objectList 对象list * @param getterFn get方法 * @param * @return */ public static List collectToList(List objectList, IGetter getterFn){ if(V.isEmpty(objectList)){ return Collections.emptyList(); } String getterPropName = convertToFieldName(getterFn); return collectToList(objectList, getterPropName); } /** * 从list对象列表中提取Id主键值到新的List * @param objectList 对象list * @param * @return */ public static List collectIdToList(List objectList){ if(V.isEmpty(objectList)){ return Collections.emptyList(); } return collectToList(objectList, Cons.FieldName.id.name()); } /** * 从list对象列表中提取指定属性值到新的List * @param objectList * @param getterPropName * @param * @return */ public static List collectToList(List objectList, String getterPropName){ if(V.isEmpty(objectList)){ return Collections.emptyList(); } List fieldValueList = new ArrayList(objectList.size()); try{ for(E object : objectList){ Object fieldValue = getProperty(object, getterPropName); // E类型中的提取的字段值不需要进行重复判断,如果一定要查重,那应该使用Set代替List if (fieldValue != null) { if (fieldValue instanceof Collection) { fieldValueList.addAll((Collection) fieldValue); } else { fieldValueList.add(fieldValue); } } } } catch (Exception e){ log.warn("提取属性值异常, getterPropName={}", getterPropName, e); } return fieldValueList; } /** * 从list对象列表中提取指定属性值到新的List * @param objectList * @param getterPropName * @param hasNullFlags 是否有null值标记参数 * @param * @return */ @Deprecated public static List collectToList(List objectList, String getterPropName, boolean[] hasNullFlags){ if(V.isEmpty(objectList)){ return Collections.emptyList(); } List fieldValueList = new ArrayList(objectList.size()); try{ for(E object : objectList){ Object fieldValue = getProperty(object, getterPropName); if(fieldValue == null){ hasNullFlags[0] = true; } // E类型中的提取的字段值不需要进行重复判断,如果一定要查重,那应该使用Set代替List fieldValueList.add(fieldValue); } } catch (Exception e){ log.warn("提取属性值异常, getterPropName={}", getterPropName, e); } return fieldValueList; } /** * 绑定map中的属性值到list * @param setFieldFn * @param getFieldFun * @param fromList * @param valueMatchMap * @param */ public static void bindPropValueOfList(ISetter setFieldFn, List fromList, IGetter getFieldFun, Map valueMatchMap){ if(V.isEmpty(fromList)){ return; } // function转换为字段名 String setterFieldName = convertToFieldName(setFieldFn), getterFieldName = convertToFieldName(getFieldFun); bindPropValueOfList(setterFieldName, fromList, getterFieldName, valueMatchMap); } /** * 从对象集合提取某个属性值到list中 * @param setterFieldName * @param fromList * @param getterFieldName * @param valueMatchMap * @param */ public static void bindPropValueOfList(String setterFieldName, List fromList, String getterFieldName, Map valueMatchMap){ if(V.isEmpty(fromList) || V.isEmpty(valueMatchMap)){ return; } try{ for(E object : fromList){ Object fieldValue = getProperty(object, getterFieldName); // 该obj的字段值为空,在Map中也必然不存在对应值 if (V.isEmpty(fieldValue)) { continue; } Object value; if(valueMatchMap.containsKey(fieldValue)){ value = valueMatchMap.get(fieldValue); } else{ // 可能是类型不匹配,转为String尝试 String fieldValueStr = String.valueOf(fieldValue); // 获取到当前的value value = valueMatchMap.get(fieldValueStr); } // 赋值 setProperty(object, setterFieldName, value); } } catch (Exception e){ log.warn("设置属性值异常, setterFieldName={}", setterFieldName, e); } } /** * 克隆对象 * @param ent * @param * @return */ public static T cloneBean(T ent){ // 克隆对象 try{ T cloneObj = (T)org.springframework.beans.BeanUtils.instantiateClass(ent.getClass()); copyProperties(ent ,cloneObj); return cloneObj; } catch (Exception e){ log.warn("Clone Object {} error", ent.getClass().getSimpleName(), e); return ent; } } /** * 转换方法引用为属性名 * @param fn * @return */ public static String convertToFieldName(IGetter fn) { SerializedLambda lambda = getSerializedLambda(fn); return PropertyNamer.methodToProperty(lambda.getImplMethodName()); } /** * 转换方法引用为属性名 * @param fn * @return */ public static String convertToFieldName(ISetter fn) { SerializedLambda lambda = getSerializedLambda(fn); return PropertyNamer.methodToProperty(lambda.getImplMethodName()); } /** * 转换SFunction为属性名 * @param getterFn * @param * @return */ public static String convertSFunctionToFieldName(SFunction getterFn) { LambdaMeta lambdaMeta = LambdaUtils.extract(getterFn); return PropertyNamer.methodToProperty(lambdaMeta.getImplMethodName()); } /** * 获取类所有属性(包含父类中属性) * @param clazz * @return */ public static List extractAllFields(Class clazz){ return extractClassFields(clazz, true,null); } /** * 获取类所有属性(包含父类中属性) * @param clazz * @return */ public static List extractAllFields(Class clazz, boolean excludeSpecial){ return extractClassFields(clazz, excludeSpecial,null); } /** * 获取类所有属性(包含父类中属性) * @param clazz * @return */ public static List extractFields(Class clazz, Class annotation){ return extractClassFields(clazz, false, annotation); } /** * 获取类的指定属性(包含父类中属性) * @param clazz * @param fieldName * @return */ public static Field extractField(Class clazz, String fieldName) { return ReflectionUtils.findField(clazz, fieldName); } /** * 获取数据表的列名(驼峰转下划线蛇形命名) *
* 列名取值优先级: @TableField.value > field.name * * @param field * @return */ public static String getColumnName(Field field) { String columnName = null; if (field.isAnnotationPresent(TableField.class)) { columnName = field.getAnnotation(TableField.class).value(); } else if(field.isAnnotationPresent(TableId.class)) { columnName = field.getAnnotation(TableId.class).value(); } return S.getIfEmpty(columnName, () -> S.toSnakeCase(field.getName())); } /** * 获取目标类 * @param instance * @return */ public static Class getTargetClass(Object instance) { return (instance instanceof Class) ? (Class) instance : AopProxyUtils.ultimateTargetClass(instance); } /** * 从实例中获取目标对象的泛型定义类class * @param instance 对象实例 * @param index * @return */ public static Class getGenericityClass(Object instance, int index){ Class hostClass = getTargetClass(instance); ResolvableType resolvableType = ResolvableType.forClass(hostClass); if(resolvableType.getSuperType().getType().getTypeName().equals(Object.class.getName()) && V.notEmpty(resolvableType.getInterfaces())) { resolvableType = resolvableType.getInterfaces()[0]; } else { resolvableType = resolvableType.getSuperType(); ResolvableType[] types = resolvableType.getGenerics(); // 逐级向上找父类 if (V.isEmpty(types) || index >= types.length) { resolvableType = resolvableType.getSuperType(); types = resolvableType.getGenerics(); if (V.isEmpty(types) || index >= types.length) { resolvableType = resolvableType.getSuperType(); } } } ResolvableType[] types = resolvableType.getGenerics(); if(V.isEmpty(types) || index >= types.length){ types = resolvableType.getSuperType().getGenerics(); } if(V.notEmpty(types) && types.length > index){ return types[index].resolve(); } log.debug("无法从 {} 类定义中获取第 {} 个泛型类", hostClass.getName(), index); return null; } /** * 转换labelValueList为Map *

* 需确保Label唯一 * * @param labelValueList * @return */ public static Map convertLabelValueList2Map(List labelValueList) { if (V.notEmpty(labelValueList)) { return labelValueList.stream().collect(Collectors.toMap(LabelValue::getLabel, LabelValue::getValue)); } return Collections.EMPTY_MAP; } /** * 根据指定Key对list去重 * @param list * @param getterFn * @param * @return 去重后的list */ public static List distinctByKey(List list, Function getterFn){ return list.stream().filter(distinctPredicate(getterFn)).collect(Collectors.toList()); } /** * 去重的辅助方法 * @param getterFn * @param * @return */ private static Predicate distinctPredicate(Function getterFn) { Set seen = ConcurrentHashMap.newKeySet(); return t -> seen.add(getterFn.apply(t)); } /** * 获取类对应的Lambda * @param fn * @return */ public static SerializedLambda getSerializedLambda(Serializable fn){ SerializedLambda lambda = null; try{ Method method = fn.getClass().getDeclaredMethod("writeReplace"); method.setAccessible(Boolean.TRUE); lambda = (SerializedLambda) method.invoke(fn); } catch (Exception e){ log.error("获取SerializedLambda异常, class={}", fn.getClass().getSimpleName(), e); } return lambda; } /** * 转换Getter数组为字段名数组 * @param getterFns * @param * @return */ @SafeVarargs private static String[] convertGettersToFields(IGetter... getterFns){ if (V.isEmpty(getterFns)) { return ArrayUtils.EMPTY_STRING_ARRAY; } int length = getterFns.length; String[] fields = new String[length]; for (int i = 0; i < length; i++) { fields[i] = convertToFieldName(getterFns[i]); } return fields; } /** * 清除属性值值 * * @param object 对象 * @param fieldNameList 属性名称列表 */ public static void clearFieldValue(Object object, List fieldNameList) { if (fieldNameList == null) { return; } BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(object); for (String fieldName : fieldNameList) { wrapper.setPropertyValue(fieldName, null); } } /** * 转换集合中的string类型id值为指定类型 * @param values * @param fieldType * @return */ public static Collection convertIdValuesToType(Collection values, Class fieldType) { if(V.isEmpty(values)) { return values; } if(V.equals(values.iterator().next().getClass(), fieldType)) { return values; } Collection formatValues = new ArrayList(values.size()); for(Object value : values) { formatValues.add(convertIdValueToType(value, fieldType)); } return formatValues; } /** * 转换string类型id值为指定类型 * @param value * @param fieldType * @return */ public static Object convertIdValueToType(Object value, Class fieldType) { if(V.isEmpty(value)) { return null; } if(Long.class.equals(fieldType)) { return Long.parseLong(S.valueOf(value)); } if(Integer.class.equals(fieldType)) { return Integer.parseInt(S.valueOf(value)); } return value; } /** * 获取字段的真实类型(集合取泛型参数) * @param clazz * @param fieldName * @return */ public static Class getFieldActualType(Class clazz, String fieldName) { Field field = extractField(clazz, fieldName); if (field == null) { log.warn("class {} 中无字段 {}", clazz.getName(), fieldName); return null; } return getFieldActualType(field); } /** * 获取字段的真实类型(集合取泛型参数) * @param field * @return */ public static Class getFieldActualType(Field field) { Type genericType = field.getGenericType(); if(genericType instanceof Class) { return (Class) genericType; } // 得到泛型里的class类型对象 else if (genericType instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) genericType; return (Class)pt.getActualTypeArguments()[0]; } else{ log.warn("非预期的GenericType : {}", genericType.getTypeName()); return null; } } /** * 初始化fields * @param beanClazz * @return */ private static List extractClassFields(Class beanClazz, boolean excludeStaticFinal, Class annotation){ List fieldList = new ArrayList<>(); Set fieldNameSet = new HashSet<>(); loopFindFields(beanClazz, excludeStaticFinal, annotation, fieldList, fieldNameSet); return fieldList; } /** * 循环向上查找fields * @param beanClazz * @param annotation * @param fieldList * @param fieldNameSet */ private static void loopFindFields(Class beanClazz, boolean excludeSpecial, Class annotation, List fieldList, Set fieldNameSet){ if(beanClazz == null) { return; } Field[] fields = beanClazz.getDeclaredFields(); if (V.notEmpty(fields)) { for (Field field : fields) { // 被重写属性,以子类的为准 if (!fieldNameSet.add(field.getName())) { continue; } if(excludeSpecial) { //忽略static,以及final,transient int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isTransient(modifiers)) { continue; } } if (annotation == null || field.getAnnotation(annotation) != null) { fieldList.add(field); } } } loopFindFields(beanClazz.getSuperclass(), excludeSpecial, annotation, fieldList, fieldNameSet); } }