对象被更新后、获取更新了的属性和值

236 阅读1分钟

业务背景

我们经常在开发中记录一些Log、比如说更新了一个对象、我们需要记录一下这个对象的哪些值被更新了、以及更新前后值分别是什么。庆幸java为我们提供了反射的机制。我们可以利用反射去实现此功能

方法实现

public static List<Map<String, String>> getChange(Object originObject, Object newObject)
    throws IntrospectionException, InvocationTargetException, IllegalAccessException {
    // 存在为null比价就没意义了
    if (ObjectUtils.anyNull(originObject, newObject)) {
        return null;
    }
    // 不同类型无法比较
    if (ObjectUtils.notEqual(originObject.getClass(), newObject.getClass())) {
        return null;
    }
    // 内容都相等所以没必要比较
    if (Objects.deepEquals(originObject, newObject)) {
        return Lists.newArrayList();
    }
    Map<String, String> originFieldValueMap = Maps.newHashMap();
    Map<String, String> newFieldValueMap = Maps.newHashMap();
    Field[] declaredFields = originObject.getClass().getDeclaredFields();
    for (Field field : declaredFields) {
        // 检查Field是否为合成字段、如果该字段是合成字段则不进行比较
        if (field.isSynthetic()) {
            continue;
        }
        // 实现方式1
        // field.setAccessible(true);
        // Object o = field.get(originObject);
        // Object n = field.get(originObject);
        // 实现方式2
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), originObject.getClass());
        Method readMethod = propertyDescriptor.getReadMethod();
        Object originValue = readMethod.invoke(originObject);
        Object newValue = readMethod.invoke(newObject);
        if (Objects.deepEquals(originValue, newValue)) {
            // 值不相等的话记录属性和值
            originFieldValueMap.put(field.getName(), Objects.isNull(originValue) ? null : originValue.toString());
            newFieldValueMap.put(field.getName(), Objects.isNull(newValue) ? null : newValue.toString());
        }
    }
    List<Map<String, String>> changes = Lists.newArrayList();
    changes.add(originFieldValueMap);
    changes.add(newFieldValueMap);
    return changes;
}