利用反射原理记录Object对象属性变化

2,359 阅读3分钟

本文已参与好文召集令活动,点击查看 : 后端、大前端双赛道投稿,2万元奖池等你挑战!

前言

开发过程中,日志记录往往是系统中必不可少的环节,大致可以分为两种情况:第一种,系统日志,类似于登录日志、接口调用日志等,此类型的主要用于记录系统的访问情况以及接口方法的被调用情况,主要为开发人员所使用,可以通过注解结合aop原理实现,通过扫描指定方法并在方法添加哪些开头的注解被写入日志的规则来实现;第二种,为业务日志,主要用于记录系统中某些业务的变化或属性的改变,比如业务流转过程中记录状态的变化或对象属性的变化,此类型主要用于查询业务轨迹使用,便于记录系统中的操作记录,主要被系统操作者使用。

背景

本文基于开发实际场景中的业务日志记录,简要讲解下系统操作者修改对象属性的情况下,利用java反射原理记录属性变化的过程,代码主要流程分为3大步骤:声明自定义注解、实体类引用、方法测试。话不多说,请看代码:

1.声明自定义注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldChangeConfig {

    public String change();
}

2.实体类引用

public class StationEntity {

	private String stationId; //id
	private String stationNo; // 油站编号
	@FieldChangeConfig(change="名称变化")
	private String stationName; // 油站名称
	@FieldChangeConfig(change="地址变化")
	private String stationAddr; // 油站地址
	private String stationLeader; //负责人id
	private String leaderName; // 负责人名称
	private String stationTel; // 联系方式
	private String maintainerNo; // 维修承包商编号
	private String maintainerNames; // 维修承包商名称

        此处省略属性的set、get方法
}

3.方法测试

public static void main(String[] args) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException{
        StationEntity a1 = new StationEntity();
        a1.setStationName("油站1");
        a1.setStationAddr("地址1");

        StationEntity a2 = new StationEntity();
        a2.setStationName("油站2");
        a2.setStationAddr("地址2");

        Map<String, List<Object>> map = getFieldChange(a1, a2,StationEntity.class);
        String modifyContent = "";
        if(!map.isEmpty()){

            for(String s : map.keySet()){
                System.out.println(s+":" + map.get(s).get(0)+"-"+map.get(s).get(1));
                modifyContent +=  s + ":" + map.get(s).get(0)+"-"+map.get(s).get(1) +"; ";
            }
        }
        System.out.println("修改内容:" + modifyContent);

    }
    
    public static Map<String, List<Object>> getFieldChange(Object a1, Object a2,Class clazz) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Map<String, List<Object>> map = new HashMap<String, List<Object>>();
        //获取当前类的实例域(即所有属性)
        Field[] fields = clazz.getDeclaredFields();
        for(Field f : fields){
            //循环属性信息,获取该实例域上的注解
            FieldChangeConfig annotation = f.getAnnotation(FieldChangeConfig.class);
            if(annotation == null){
                continue;
            }
            //获取注解中的内容
            String change = annotation.change();
            //使用javeBean PropertyDescriptor类型 获取bean的get方法
            PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
            //获取get方法
            Method readMethod = pd.getReadMethod();
            Object o1 = readMethod.invoke(a1);//实体对象1的属性
            Object o2 = readMethod.invoke(a2);//实体对象2的属性
            
            //比较属性信息并将信息的变化以list的形式放入map中,main方法测试时从map中取值并拼接
            if(o1==null && o2==null){
                continue;
            }
            if(o1==null || o2 ==null){
                List<Object> list = new ArrayList<Object>();
                list.add(o1);
                list.add(o2);
                map.put(change, list);
                continue;
            }

            if(!o1.equals(o2)){
                List<Object> list = new ArrayList<Object>();
                list.add(o1);
                list.add(o2);
                map.put(change, list);
                continue;
            }
        }
        return map;
    }

4.结果显示

微信图片_20210705223618.jpg

好了,这篇文章对你有帮助吗,如果满意的话记得给小编点赞哦,你的认可和喜欢是小编持续输出的最大动力。