java属性修改前后_java 记录对象前后修改的内容(工具类)
有時(shí)候業(yè)務(wù)需要,需記錄一條記錄的修改歷史,但是不能為完成任務(wù)而硬編碼,不靠譜
這種情況可以使用java反射來完成
對對象屬性的描述可以通過自定義注解來完成,讀取里面的屬性進(jìn)而記錄修改歷史。
在對象的屬性上面加上注解,value設(shè)置為屬性的中文描述
工具了代碼如下
util類(BeanChangeUtil)
importjava.beans.PropertyDescriptor;importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.util.Arrays;public class BeanChangeUtil{publicString contrastObj(Object oldBean, Object newBean) {//創(chuàng)建字符串拼接對象
StringBuilder str = newStringBuilder();//轉(zhuǎn)換為傳入的泛型T
T pojo1 =(T) oldBean;
T pojo2=(T) newBean;//通過反射獲取類的Class對象
Class clazz =pojo1.getClass();//獲取類型及字段屬性
Field[] fields =clazz.getDeclaredFields();returnjdk8Before(fields, pojo1, pojo2, str,clazz);//return jdk8OrAfter(fields, pojo1, pojo2, str,clazz);
}//jdk8 普通循環(huán)方式
publicString 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= newPropertyDescriptor(field.getName(), clazz);//獲取對應(yīng)屬性值
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();
}returnstr.toString();
}//lambda表達(dá)式,表達(dá)式內(nèi)部的變量都是final修飾,需要傳入需要傳入final類型的數(shù)組
publicString 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= newPropertyDescriptor(f.getName(), clazz);//獲取對應(yīng)屬性值
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();
}
}
});returnstr.toString();
}
}
自定義注解(PropertyMsg)
@Target
表示該注解可以用于什么地方,可能的ElementType參數(shù)有:
CONSTRUCTOR:構(gòu)造器的聲明
FIELD:域聲明(包括enum實(shí)例)
LOCAL_VARIABLE:局部變量聲明
METHOD:方法聲明
PACKAGE:包聲明
PARAMETER:參數(shù)聲明
TYPE:類、接口(包括注解類型)或enum聲明
@Retention
表示需要在什么級別保存該注解信息。可選的RetentionPolicy參數(shù)包括:
SOURCE:注解將被編譯器丟棄
CLASS:注解在class文件中可用,但會被VM丟棄
RUNTIME:VM將在運(yùn)行期間保留注解,因此可以通過反射機(jī)制讀取注解的信息。
@Document
將注解包含在Javadoc中
@Inherited
允許子類繼承父類中的注解
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inheritedpublic @interfacePropertyMsg {
String value();
}
使用方式test
public classTestChange {public static voidmain(String[] args) {
TestChange u1= new TestChange("我是誰", "ok", 30,"劉德華");
TestChange u2= new TestChange("我在哪", "no", 20,"郭富城");
BeanChangeUtil t = new BeanChangeUtil<>();
String str=t.contrastObj(u1, u2);if (str.equals("")) {
System.out.println("未有改變");
}else{
System.out.println(str);
}
}publicTestChange() {
}publicTestChange(String about, String lock, Integer age, String name) {this.about =about;this.lock =lock;this.age =age;this.name =name;
}
@PropertyMsg("關(guān)于")privateString about;privateString lock;
@PropertyMsg("年齡")privateInteger age;
@PropertyMsg("姓名")privateString name;
get... set... 省略
}
OK,到位
原文出處:https://www.cnblogs.com/chywx/p/10634547.html
總結(jié)
以上是生活随笔為你收集整理的java属性修改前后_java 记录对象前后修改的内容(工具类)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java获取系统运行日志文件_java
- 下一篇: a java runtime envi_