Java项目C中 有一处逻辑,对于资源数据(类型为ResourceItem,拥有int/double/boolean/String类型数十个字段),需要比对资源数据每次变更的差异,并描述出变更情况。并非所有的字段都需要比对,如id字段则不参与比对。
 
依次比对每一个字段编写代码比对,将是个重苦力活。高级语言给予了我们诸多便利,应当加以利用。
 
首先定义自己的注解,value值用作字段描述
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RevisionColumn {
String value();
}
 
为ResourceItem所有待比对字段添加该注解,如
public class ResourceItem {
private int id;
private int revision;
private ResourceItemStatus status; @RevisionColumn("节点")
private String node; @RevisionColumn("是否物理隔离")
private boolean physicalIsolation; @RevisionColumn("整机:单盘上限(%)")
private int machineDiskLimit; //...
}
 
介绍比对逻辑前,首先定义记录对象字段差异的实体类型
public class FieldChangeInfo implements Serializable{
private String propertyName;
private String propertyHeader;
private Object from;
private Object to; public FieldChangeInfo() {
} public FieldChangeInfo(String propertyName, String propertyHeader, Object from, Object to) {
this.propertyName = propertyName;
this.propertyHeader = propertyHeader;
this.from = from;
this.to = to;
} @Override
public boolean equals(Object obj) {
if (!(obj instanceof FieldChangeInfo))
return false;
if (obj == this)
return true; FieldChangeInfo rhs = (FieldChangeInfo) obj;
return new EqualsBuilder().
append(propertyName, rhs.propertyName).
append(propertyHeader, rhs.propertyHeader).
append(from, rhs.from).
append(to, rhs.to).
isEquals();
} public String getPropertyName() {
return propertyName;
} public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
} public String getPropertyHeader() {
return propertyHeader;
} public void setPropertyHeader(String propertyHeader) {
this.propertyHeader = propertyHeader;
} public Object getFrom() {
return from;
} public void setFrom(Object from) {
this.from = from;
} public Object getTo() {
return to;
} public void setTo(Object to) {
this.to = to;
}
}

FieldChangeInfo

 
Resource数据比对逻辑,实现如下工具方法
1、参数接受ResourceItem新旧两个对象
2、通过反射,class.getDeclaredFields获取类型的所有字段
3、调用Field实例的getAnnotation方法,获取RevisionColumn注解对象,若不为null,则说明该字段设置了该注解,进行比对
4、获取字段值,检测空引用,调用equals方法做值比对,出现不匹配,则创建FiledChangeInfo对象记录差异信息
5、返回差异信息集合

    public static List<FieldChangeInfo> getResourceItemFieldChangeInfo(ResourceItem originalItem, ResourceItem updatedItem) {
try {
List<FieldChangeInfo> fieldChangeInfos = new LinkedList<>(); for (Field field : ResourceItem.class.getDeclaredFields()) {
RevisionColumn revisionColumn = field.getAnnotation(RevisionColumn.class);
if (revisionColumn != null)
{
field.setAccessible(true);
Object originalValue = field.get(originalItem);
Object updatedValue = field.get(updatedItem); if (originalValue == null && updatedValue == null)
continue; if (originalValue == null || !originalValue.equals(updatedValue)){
FieldChangeInfo fieldChangeInfo = new FieldChangeInfo();
fieldChangeInfo.setFrom(originalValue);
fieldChangeInfo.setTo(updatedValue); fieldChangeInfo.setPropertyName(field.getName());
fieldChangeInfo.setPropertyHeader(revisionColumn.value()); fieldChangeInfos.add(fieldChangeInfo);
}
}
}
return fieldChangeInfos;
} catch (IllegalAccessException e) {
throw new RuntimeException("检测ResourceItem字段变更时出现异常");
}
}

getResourceItemFieldChangeInfo

 
若有必要,则可以稍加重构转换为泛型方法,支持何种数据类型的差异性检测

[原创]Java使用反射及自定义注解实现对象差异性比较的更多相关文章

  1. java 利用反射完成自定义注解

    元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明.Java5.0定义的元注解: 1.@ ...

  2. 利用反射跟自定义注解拼接实体对象的查询SQL

    前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...

  3. Android面试基础(一)IOC(DI)框架(ViewUtils)讲解_反射和自定义注解类

    1. Android中的IOC(DI)框架 1.1 ViewUtils简介(xUtils中的四大部分之一) IOC: Inverse of Controller 控制反转. DI: Dependenc ...

  4. Java反射与自定义注解

    反射,在Java常用框架中屡见不鲜.它存在于java.lang.reflact包中,就我的认识,它可以拿到类的字段和方法,及构造方法,还可以生成对象实例等.对深入的机制我暂时还不了解,本篇文章着重在使 ...

  5. java基础知识:自定义注解

    转自 深入了解注解 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解的作用就是负责注解其他注解.J ...

  6. 【java开发系列】—— 自定义注解

    之前在开发中,就总纳闷,为什么继承接口时,会出现@Override注解,有时候还会提示写注解@SuppressWarnings? 原来这是java特有的特性,注解! 那么什么是注解呢? 注解就是某种注 ...

  7. JAVA中如何定义自定义注解

    了解注解 注解是Java1.5,JDK5.0引用的技术,与类,接口,枚举处于同一层次 .它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来对这些元素进行说明,注释 . 在Java中,自带 ...

  8. AOP通过反射获取自定义注解

    自定义注解: @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component publ ...

  9. [原创]java WEB学习笔记15:域对象的属性操作(pageContext,request,session,application) 及 请求的重定向和转发

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

随机推荐

  1. LeetCode OJ:Ugly Number(丑数)

    Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers ...

  2. DMD数字微镜

    Digital Micromirror Device DMD技术于1987年被发明,到1996年春走向市场.DMD是一个真正的微光机电系统(MOEMS),该器件是利用CMOS工艺和微机械加工(MEMS ...

  3. Java基础学习-extends继承(成员变量,局部变量,成员方法)

    package extend; /*面向对象-继承: * 多个类的共同成员变量和成员方法.抽取到另一个类中(父类),我们多个类就可以访问到父类的成员了 * */ class Game{ String ...

  4. Web目录结构

    /: Web应用的跟目录,该目录下所有文件在客户端都可以访问(JSP,HTML) /WEB-INF: 存放应用使用的各种资源.该目录及其子目录对客户端都是不可以访问的, 其中包括web.xml(部署表 ...

  5. Handling CLIK AS3 Compile Error 1152 & 5000

    Handling CLIK AS3 Compile Error 1152 & 5000 Action You add a CLIK AS3 component from CLIK_Compon ...

  6. Kivy: Building GUI and Mobile apps with Python

    Intro Python library for building gui apps (think qt, gdk,processing) build from ground up for lates ...

  7. 有状态与无状态 cookie session

    服务器所维护的与客户交互活动的信息称为状态信息.不保存任何状态信息的服务器称为无状态服务器(stateless server),反之则称为有状态服务器(stateful server). 面向连接对应 ...

  8. Java基础总结大全

    一.基础知识: 1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. java语言是跨平台,jvm不是跨平台的. J ...

  9. Hibernate HQL查询(2)

    hql是面向对象查询,格式:from + 类名 + 类对象 + where + 对象的属性 sql是面向数据库表查询,格式:from + 表名 + where + 表中字段 1.查询 一般在Hiber ...

  10. 【模板】NOIP模板汇总

    图论 数据结构 数学 其他: 洛谷模板:a,b两个字符串,求b串在a串中出现的位置 #include<iostream> #include<cstdio> #include&l ...