java 記錄對象先後修改的內容(工具類)

有時候業務須要,需記錄一條記錄的修改歷史,可是不能爲完成任務而硬編碼,不靠譜java

這種狀況能夠使用java反射來完成git

對對象屬性的描述能夠經過自定義註解來完成,讀取裏面的屬性進而記錄修改歷史。github

在對象的屬性上面加上註解,value設置爲屬性的中文描述數組

工具了代碼以下app

util類(BeanChangeUtil)工具

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class BeanChangeUtil<T> {
    public String contrastObj(Object oldBean, Object newBean) {
        // 建立字符串拼接對象
        StringBuilder str = new StringBuilder();
        // 轉換爲傳入的泛型T
        T pojo1 = (T) oldBean;
        T pojo2 = (T) newBean;
        // 經過反射獲取類的Class對象
        Class clazz = pojo1.getClass();
        // 獲取類型及字段屬性
        Field[] fields = clazz.getDeclaredFields();
        return jdk8Before(fields, pojo1, pojo2, str,clazz);
//        return jdk8OrAfter(fields, pojo1, pojo2, str,clazz);
    }

    // jdk8 普通循環方式
    public String jdk8Before(Field[] fields,T pojo1,T pojo2,StringBuilder str,Class clazz){
        int i = 1;
        try {
            for (Field field : fields) {
                if(field.isAnnotationPresent(PropertyMsg.class)){
                    PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                    // 獲取對應屬性值
                    Method getMethod = pd.getReadMethod();
                    Object o1 = getMethod.invoke(pojo1);
                    Object o2 = getMethod.invoke(pojo2);
                    if (o1 == null || o2 == null) {
                        continue;
                    }
                    if (!o1.toString().equals(o2.toString())) {
                        str.append(i + "、" + field.getAnnotation(PropertyMsg.class).value() + ":" + "修改前=>" + o1 + ",修改後=>" + o2 + "\n");
                        i++;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str.toString();
    }

    // lambda表達式,表達式內部的變量都是final修飾,須要傳入須要傳入final類型的數組
    public String jdk8OrAfter(Field[] fields, T pojo1, T pojo2, StringBuilder str, Class clazz){
        final int[] i = {1};
        Arrays.asList(fields).forEach(f -> {
            if(f.isAnnotationPresent(PropertyMsg.class)){
                try {
                    PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
                    // 獲取對應屬性值
                    Method getMethod = pd.getReadMethod();
                    Object o1 = getMethod.invoke(pojo1);
                    Object o2 = getMethod.invoke(pojo2);
                    if (o1 == null || o2 == null) {
                        return;
                    }
                    if (!o1.toString().equals(o2.toString())) {
                        str.append(i[0] + "、" + f.getAnnotation(PropertyMsg.class).value() + ":" + "修改前=>" + o1 + "\t修改後=>" + o2 + "\n");
                        i[0]++;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        return str.toString();
    }
}

自定義註解(PropertyMsg)ui

@Targetthis

表示該註解能夠用於什麼地方,可能的ElementType參數有:編碼

  CONSTRUCTOR:構造器的聲明spa

  FIELD:域聲明(包括enum實例)

  LOCAL_VARIABLE:局部變量聲明

  METHOD:方法聲明

  PACKAGE:包聲明

  PARAMETER:參數聲明

  TYPE:類、接口(包括註解類型)或enum聲明

@Retention

表示須要在什麼級別保存該註解信息。可選的RetentionPolicy參數包括:

  SOURCE:註解將被編譯器丟棄

  CLASS:註解在class文件中可用,但會被VM丟棄

  RUNTIME:VM將在運行期間保留註解,所以能夠經過反射機制讀取註解的信息。

@Document

將註解包含在Javadoc中

@Inherited

容許子類繼承父類中的註解

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface PropertyMsg {
    String value();
}

使用方式test

public class TestChange {

    public static void main(String[] args) {
        TestChange u1 = new TestChange("我是誰", "ok", 30,"劉德華");
        TestChange u2 = new TestChange("我在哪", "no", 20,"郭富城");
        BeanChangeUtil<TestChange> t = new BeanChangeUtil<>();
        String str = t.contrastObj(u1, u2);
        if (str.equals("")) {
            System.out.println("未有改變");
        } else {
            System.out.println(str);
        }
    }

    public TestChange() {
    }

    public TestChange(String about, String lock, Integer age, String name) {
        this.about = about;
        this.lock = lock;
        this.age = age;
        this.name = name;
    }

    @PropertyMsg("關於")
    private String about;

    private String lock;

    @PropertyMsg("年齡")
    private Integer age;

    @PropertyMsg("姓名")
    private String name;

    get... set... 省略
}

OK,到位

 https://github.com/chywx/JavaSE_chy

相關文章
相關標籤/搜索