码迷,mamicode.com
首页 > 编程语言 > 详细

[原创]Java使用反射及自定义注解实现对象差异性比较

时间:2015-01-04 21:17:51      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

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使用反射及自定义注解实现对象差异性比较

标签:

原文地址:http://www.cnblogs.com/gods/p/4202023.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!