/**
* 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个Map分别存oldObject,newObject此属性名的值
* @param oldObject 进行属性比较的对象1
* @param newObject 进行属性比较的对象2
* @return 属性差异比较结果map
*/
public static Map<String, Map<String,Object>> compareFields(Object oldObject, Object newObject) {}
/**
* 合并两个map中的元素
* @param map1 Map<String, Map<String,Object>>
* @param map2 Map<String, Map<String,Object>>
* @return 合并后的Map<String, Map<String,Object>>
*/
public static Map<String, Map<String,Object>> mergeMap(Map<String, Map<String,Object>> map1, Map<String, Map<String,Object>> map2) {}
/**
* 可以给定一个map key存储源对象的字段值,value存储目标对象的字段,可以实现两个不同字段名称间的属性复制
* @param source 源对象
* @param target 目标对象
* @param map 字段映射map
*/
public static void copyProperties(Object source, Object target,Map<String,String> map) throws BeansException {}
import com.sun.istack.internal.Nullable;
import org.springframework.beans.*;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Timestamp;
import java.util.*;
/**
* 类工具类
* @author : Xiewy <br/>
* @date : 2022/5/30 14:35 <br/>
*/
@Component
public class CheckBeanUtils {
/**
* 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个Map分别存oldObject,newObject此属性名的值
* @param oldObject 进行属性比较的对象1
* @param newObject 进行属性比较的对象2
* @return 属性差异比较结果map
*/
public static Map<String, Map<String,Object>> compareFields(Object oldObject, Object newObject) {
Map<String, Map<String, Object>> map = null;
try{
/**
* 只有两个对象都是同一类型的才有可比性
*/
if (oldObject.getClass() == newObject.getClass()) {
map = new HashMap<String, Map<String,Object>>();
Class clazz = oldObject.getClass();
//获取object的所有属性
PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz,Object.class).getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//遍历获取属性名
String name = pd.getName();
//获取属性的get方法
Method readMethod = pd.getReadMethod();
// 在oldObject上调用get方法等同于获得oldObject的属性值
Object oldValue = readMethod.invoke(oldObject);
// 在newObject上调用get方法等同于获得newObject的属性值
Object newValue = readMethod.invoke(newObject);
if(oldValue instanceof List){
continue;
}
if(newValue instanceof List){
continue;
}
if(oldValue instanceof Timestamp){
oldValue = new Date(((Timestamp) oldValue).getTime());
}
if(newValue instanceof Timestamp){
newValue = new Date(((Timestamp) newValue).getTime());
}
if(oldValue == null && newValue == null){
continue;
}else if(oldValue == null && newValue != null){
Map<String,Object> valueMap = new HashMap<String,Object>();
valueMap.put("oldValue",oldValue);
valueMap.put("newValue",newValue);
map.put(name, valueMap);
continue;
}
if (!oldValue.equals(newValue)) {// 比较这两个值是否相等,不等就可以放入map了
Map<String,Object> valueMap = new HashMap<String,Object>();
valueMap.put("oldValue",oldValue);
valueMap.put("newValue",newValue);
map.put(name, valueMap);
}
}
}
}catch(Exception e){
e.printStackTrace();
}
return map;
}
/**
* 合并两个map中的元素
* @param map1 Map<String, Map<String,Object>>
* @param map2 Map<String, Map<String,Object>>
* @return 合并后的Map<String, Map<String,Object>>
*/
public static Map<String, Map<String,Object>> mergeMap(Map<String, Map<String,Object>> map1, Map<String, Map<String,Object>> map2) {
Map<String, Map<String,Object>> map = new HashMap<>();
if (map1 == null && map2 == null){
return null;
}
if (map1 == null){
return map2;
}
if (map2 == null){
return map1;
}
map.putAll(map1);
map.putAll(map2);
return map;
}
/**
* BeanUtils.copyProperties,深层copy是原数据为null不进行覆盖
* @param source 资源类
* @return
*/
public static String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set emptyNames = new HashSet();
for(java.beans.PropertyDescriptor pd : pds) {
//检查此属性的值是否为 null 然后将其添加到集合中
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return (String[]) emptyNames.toArray(result);
}
/**
* 功能描述: 属性复制
* @param source 源对象
* @param target 目标对象
* @param ignoreProperties 忽略的属性
*/
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
copyProperties(source, target, null,null, ignoreProperties);
}
/**
* 功能描述: 属性复制
*/
public static void copyProperties(Object source, Object target) throws BeansException {
copyProperties(source, target, null,null, (String[]) null);
}
/**
* 功能描述: 属性复制
* @param source 源对象
* @param target 目标对象
* @param map 字段映射map
*/
public static void copyProperties(Object source, Object target,Map<String,String> map) throws BeansException {
copyProperties(source, target, null,map, (String[]) null);
}
/**
* 拓展springBeanUtils
* 可以给定一个map key存储源对象的字段值,value存储目标对象的字段,可以实现两个不同字段名称间的属性复制
*
* @param source 源对象(bean)
* @param target 目标对象(bean)
* @param editable 将属性设置限制为的类(或接口)
* @param map 字段映射map key存储源对象的字段值,value存储目标对象的字段
* @param ignoreProperties 要忽略的属性名称数组
* @throws BeansException 如果复制失败
* @see BeanWrapper
*/
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
@Nullable Map<String, String> map, @Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
// 拿到目标对象字节码对象
Class<?> actualEditable = source.getClass();
if (editable != null) {
if (!editable.isInstance(source)) {
throw new IllegalArgumentException("Source class [" + source.getClass().getName() +
"] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
// PropertyDescriptor描述Java Bean中通过一对存储器方法(getter / setter)导出的一个属性。我们可以通过该PropertyDescriptor对bean中的该属性进行读取和写入操作,也可以设置其getter / setter。
PropertyDescriptor[] sourcePds = BeanUtils.getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
// 遍历目标对象的属性
for (PropertyDescriptor sourcePd : sourcePds) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null && (ignoreList == null || !ignoreList.contains(sourcePd.getName()))) {
PropertyDescriptor targetPd = null;
// 如果map有,则取map中的字段
if (map != null && map.get(sourcePd.getName()) != null && !"".equals(map.get(sourcePd.getName()))) {
targetPd = BeanUtils.getPropertyDescriptor(target.getClass(), map.get(sourcePd.getName()));
} else {
// 如果map没有,则找相同名称的字段
targetPd = BeanUtils.getPropertyDescriptor(target.getClass(), sourcePd.getName());
}
if (targetPd != null) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null &&
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
}
catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
}
}