项目中某些地方要求记录信息变更日志,通过反射获取属性对比新旧信息的变化情况,然后记录日志
一、创建实体类比较标志注解(只比较有注解的属性)
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 }
四、打完收功~