项目中某些地方要求记录信息变更日志,通过反射获取属性对比新旧信息的变化情况,然后记录日志
一、创建实体类比较标志注解(只比较有注解的属性)
1 import java.lang.annotation.*; 2 3 /** 4 * @Description //实体类比较标志注解 5 * @Author yangli 6 **/ 7 @Documented 8 @Target(ElementType.FIELD) 9 @Retention(RetentionPolicy.RUNTIME) 10 public @interface BeanContrast { 11 12 String fieldDesc() default "undefined"; 13 14 }
二、创建变更信息实体
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @Description //实体修改信息类 **/ @Data @NoArgsConstructor @AllArgsConstructor @Builder public class ModifyInfo {
@BeanContrast(fidldDesc="修改字段") private String modifyField;
@BeanContrast(fidldDesc="修改前")
private String beforeModify;
@BeanContrast(fidldDesc="修改后")
private String afterModify;
}
三、创建工具类
1 import lombok.extern.slf4j.Slf4j; 2 import org.apache.commons.lang3.StringUtils; 3 4 import java.beans.PropertyDescriptor; 5 import java.lang.reflect.Field; 6 import java.lang.reflect.Method; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 /** 11 * @Description //实体对象属性比较工具类 12 * @Author yangli 13 **/ 14 @Slf4j 15 public class BeanChangeUtils { 16 17 /** 18 * @Description: 比较对象下同一属性的修改 19 * @param oldBean 20 * @param newBean 21 * @Return: java.util.List<entity.ModifyInfo> 22 * @Author: yangli 23 **/ 24 public static List<ModifyInfo> contrastObj(Object oldBean, Object newBean) { 25 List<ModifyInfo> modifyInfoList = new ArrayList<>(); 26 try { 27 // 通过反射获取类的类类型及字段属性 28 Class clazzOld = oldBean.getClass(); 29 Class clazzNew = newBean.getClass(); 30 31 Field[] fields = clazzOld.getDeclaredFields(); 32 for (Field field : fields) { 33 // 检查属性上有无 自定义对比 注解 -> 无则直接跳过 34 BeanContrast contrastAnnotation = field.getAnnotation(BeanContrast.class); 35 if (contrastAnnotation == null) { 36 continue; 37 } 38 39 //获取字段名描述 40 String modifyField = contrastAnnotation.fieldDesc(); 41 42 PropertyDescriptor pdOld = new PropertyDescriptor(field.getName(), clazzOld); 43 PropertyDescriptor pdNew = new PropertyDescriptor(field.getName(), clazzNew); 44 // 获取对应属性值 45 Method getMethodOld = pdOld.getReadMethod(); 46 Object o1 = getMethodOld.invoke(oldBean); 47 Method getMethodNew = pdNew.getReadMethod(); 48 Object o2 = getMethodNew.invoke(newBean); 49 if (o1 == null && o2 == null) { 50 continue; 51 } 52 53 if(o1 == null){ 54 // o2不为null的情况 55 if(StringUtils.isNotBlank(o2.toString())) { 56 ModifyInfo modifyInfo = ModifyInfo.builder() 57 .modifyField(modifyField) 58 .beforeModify("") 59 .afterModify(o2.toString()) 60 .build(); 61 modifyInfoList.add(modifyInfo); 62 } 63 } else { 64 // O1不为null 65 if(o2 == null ) { 66 // o2为null的情况 67 if (StringUtils.isNotBlank(o1.toString())) { 68 ModifyInfo modifyInfo = ModifyInfo.builder() 69 .modifyField(modifyField) 70 .beforeModify(o1.toString()) 71 .afterModify("") 72 .build(); 73 modifyInfoList.add(modifyInfo); 74 } 75 } else { 76 // o2 不为null的情况 77 if ((StringUtils.isNotBlank(o1.toString()) || StringUtils.isNotBlank(o2.toString())) 78 && !o1.toString().equals(o2.toString())) { 79 ModifyInfo modifyInfo = ModifyInfo.builder() 80 .modifyField(modifyField) 81 .beforeModify(o1.toString()) 82 .afterModify(o2.toString()) 83 .build(); 84 modifyInfoList.add(modifyInfo); 85 } 86 } 87 } 88 } 89 } catch (Exception e) { 90 log.error("对比实体变更信息失败:", e); 91 throw new Exception("系统异常"); 92 } 93 94 return modifyInfoList; 95 } 96 97 }
四、打完收功~