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

相关文章
相关标签/搜索