java 记录对象前后修改的内容(工具类)
有时候业务需要,需记录一条记录的修改历史,但是不能为完成任务而硬编码,不靠谱
这种情况可以使用java反射来完成
对对象属性的描述可以通过自定义注解来完成,读取里面的属性进而记录修改历史。
在对象的属性上面加上注解,value设置为属性的中文描述
工具了代码如下
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)
@Target
表示该注解可以用于什么地方,可能的ElementType参数有:
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
java 记录对象前后修改的内容(工具类)的更多相关文章
- Java Class与反射相关的一些工具类
package com.opslab.util; import org.apache.log4j.Logger; import java.io.File;import java.io.IOExcept ...
- Java语言Lang包下常用的工具类介绍_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数.你可知道,有很多现成的工具类可用,并且代码质量都 ...
- java调用kettle的job和transfer工具类
package com.woaiyitiaocai.util; import java.util.Map; import java.util.UUID; import org.apache.log4j ...
- java总结第二次(剩余内容)//类和对象1
7.成员变量和局部变量 成员变量:在类中定义,用来描述对象将要有什么 局部变量:在类的方法中定义,在方法中保存临时数据 区别:作用域不同 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类内 ...
- Json:Java对象和Json文本转换工具类
Json 是一个用于 Java 对象 和 Json 文本 相互转换的工具类. 安装 下载源码 git clone https://github.com/njdi/durian.git 编译源码 cd ...
- java springboot调用第三方接口 借助hutoool工具类 爬坑
楼主是个后端小白一枚,之前没接触过后端,只学了java基本语法,还是在学校老师教的,学的很浅,什么ssh.ssm框架都没有学,最近在自学spring boot,看书学也看不是很懂,就在b站上看教学视频 ...
- java中模拟http(https)请求的工具类
在java中,特别是java web中,我们经常需要碰到的一个场景是我们需要从服务端去发送http请求,获取到数据,而不是直接从浏览器输入请求网址获得相应.比如我们想访问微信接口,获取其返回信息. 在 ...
- Java集合框架(六)—— Collections工具类
操作集合的工具类Collections Java提供了一个操作Set.List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序.查询和修改等操作,还提供了将集 ...
- poi读取excel内容工具类
该工具类可以读取excel2007,excel2003等格式的文件,xls.xlsx文件格式 package com.visolink; import org.apache.poi.hssf.user ...
随机推荐
- HDU 6085 bitset
Rikka with Candies Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- 个推Node.js 微服务实践:基于容器的一站式命令行工具链
作者:个推Node.js 开发工程师 之诺 背景与摘要 由于工程数量的快速增长,个推在实践基于 Node.js 的微服务开发的过程中,遇到了如下问题: 1. 每次新建项目都需要安装一次依赖,这些依赖之 ...
- yolo详解
文章<You Only Look Once: Unified, Real-Time Object Detection>提出方法下面简称YOLO. 目前,基于深度学习算法的一系列目标检测算法 ...
- TCP和IP的三次握手和第四次挥手
TCP握手协议 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确 ...
- AngularJS入门基础——表达式
表达式在AngularJS应用中广泛的使用,因此深入理解AngularJS如何使用并运算表达式是非常重要的. 表达式和eval非常相似,但是由于表达式由AngularJS来处理,它们有已下显著不同 ...
- MySQL ODBC 驱动安装
一.在线安装 1.yum在线安装驱动 # yum -y install unixODBC # yum -y install mysql-connector-odbc 2.配置驱动 (1)查看驱动程序相 ...
- NOIP2016-D2-T2 蚯蚓(单调队列)
构建三个单调队列(用STL),分别储存未切的蚯蚓,切后的第一段,切后的第二段,即可简单证明其单调性. 证明:设$q$为单调队列$\because a_1 \geqslant a_2 \geqslant ...
- QTP图片验证/图片比较/二进制流对比法
图片验证主要是文件对比,其中我们可以利用二进制的方法读取图片信息,然后进行对比,达到对比的效果,本例子利用fso对象的文件流的方法实现,代码如下: Public Function CompareFil ...
- cas:覆盖安装
1.首先到github上下载最新的模板代码 https://github.com/apereo/cas-overlay-template 下载完成后,导入该工程. 2.编译打包 cd cas-over ...
- @PostConstruct和@PreConstruct
详情参见:https://www.cnblogs.com/landiljy/p/5764515.html 1.@PostConstruct说明 被@PostConstruct修饰的方法会在服务器加载S ...