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

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

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

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

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

工具了代碼以下數組

util類(BeanChangeUtil)app

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)工具

@Targetui

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

  CONSTRUCTOR:構造器的聲明編碼

  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

原文出處:https://www.cnblogs.com/chywx/p/10634547.html

相關文章
相關標籤/搜索