背景
在开发过程中经常会使用到一种场景就是比较内存中的两个bean 数据有什么同。其实这种功能算是一个非常常用的场景。
使用实例说明
一共需要以下的几个模块
- FieldComparison 自定义注解,主要是标识需要比较的bean 中的字段。
- BeanCompareUtil 核心util 主要是实现compare 方法。
- FieldMapping 字段映射关系,选用可以对特定的字段进行转义。
- DefaultFieldMapping fieldMapping的实现类。可以扩展。
public class BeanCompareUtil {
public static List<BeanCompareResult> compare(Object oldBean, Object newBean)
throws InvocationTargetException, IllegalAccessException,
IntrospectionException, NullPointerException, InstantiationException, NoSuchMethodException {
if (oldBean == null || newBean == null) {
throw new IllegalArgumentException("the argument must be not null");
}
if (oldBean.getClass() != newBean.getClass()) {
return Collections.emptyList();
}
List<BeanCompareResult> list = new ArrayList<>();
Class<?> aClass = oldBean.getClass();
while (aClass != null) {
Field[] fieldList = aClass.getDeclaredFields();
for (Field field : fieldList) {
if (field.isAnnotationPresent(FieldComparison.class)) {
BeanCompareResult comResult = new BeanCompareResult();
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), aClass);
String name = pd.getName();
comResult.setCode(name);
Method getMethod = pd.getReadMethod();
Object o1 = getMethod.invoke(oldBean);
Object o2 = getMethod.invoke(newBean);
if (o2 == null) {
continue;
}
String first = null == o1 ? "" : String.valueOf(o1).trim();
String second = String.valueOf(o2).trim();
if (field.isAnnotationPresent(FieldComparison.class)) {
FieldComparison fieldComparison = field.getAnnotation(FieldComparison.class);
String value = fieldComparison.codeName();
Class<? extends FieldMapping> mapping = fieldComparison.mapping();
Method method = mapping.getMethod("mapping", Map.class);
Object invoke = method.invoke(mapping.newInstance(), new HashMap<>());
if (invoke != null) {
Map<String, String> map = (Map<String, String>) invoke;
String s = map.get(first);
String s2 = map.get(second);
comResult.setOldValue(s);
comResult.setNewValue(s2);
} else {
comResult.setOldValue(first);
comResult.setNewValue(second);
}
comResult.setName(value);
}
if (!first.equals(second)) {
list.add(comResult);
}
}
}
aClass = aClass.getSuperclass();
}
return list;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldComparison {
/**
* 字段对应的中文名从
*
* @return
*/
String codeName() default "";
/**
* 字段对应关系,如 1->下线 0->上线
* @return
*/
Class<? extends FieldMapping> mapping() default DefaultFieldMapping.class;
}
public interface FieldMapping {
Map<String, String> mapping(Map<String,String> map);
}
public class DefaultFieldMapping implements FieldMapping {
@Override
public Map<String, String> mapping(Map<String, String> map) {
return null;
}
}
使用方式
- 在需要compare 的地方加上注释
- 定义结果接受的bean
public class BeanCompareResult {
private String code;
private String name;
private String oldValue;
private String newValue;
private String extendRemark;
public String getExtendRemark() {
return extendRemark;
}
public void setExtendRemark(String extendRemark) {
this.extendRemark = extendRemark;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
@Override
public String toString() {
return "BeanCompareResult{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
", oldValue='" + oldValue + '\'' +
", newValue='" + newValue + '\'' +
", extendRemark='" + extendRemark + '\'' +
'}';
}
}
- 传入oldbean 和 newbean进行比较和接收结果。