【Java日志记录对象修改前后的变化】

今天接到一个需求,修改数据时需要记录修改详情。详情包括,被修改的字段,修改前的值和修改后的值。

解决思路

  • 分别比较修改前后两个Bean实例的所有成员变量,当值不一致时,记录变量名称,以及修改前后的值。 对于该方案,可以解决特定类型的Bean。 如果有其它类型的Bean也有这种需求,则需要新写一套逻辑,处理相应的需求。
  • 上述方案不能复用,如果有多个这样的Bean需要比较,则每个Bean都需要新写一套逻辑。然而,利用泛型和反射技术,则可以达到一次编码,多处复用的效果

实现步骤

下面,就采用泛型和反射技术来实现上述需求

  • 自定义注解
  	@Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ForUpdate {
        String fieldName() default "";
    }

  • 给Bean属性添加注解
	@Data
    @Builder
    public class Bean {
   
        private Long id; //不需要记录变化的字段,无需添加注解 @ForUpdate
       
        @ForUpdate(fieldName = "姓名") //需要记录变化的字段,需添加注解@ForUpdate
        private String name;

        @ForUpdate(fieldName = "年龄")
        private Integer age;
    }

  • 实现记录Bean修改明细
public class BeanUtils {
	
 	/**
     * 获取变更内容
     * @param newBean 更改前的Bean
     * @param oldBean 更改后的Bean
     * @param <T>
     * @return
     */
    public static <T> String getChangedFields(T newBean, T oldBean){
        Field[] fields = newBean.getClass().getDeclaredFields();
        StringBuilder builder = new StringBuilder();
        for(Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(ForUpdate.class)) {
                try {
                    Object newValue = field.get(newBean);
                    Object oldValue = field.get(oldBean);
                    if(!Objects.equals(newValue, oldValue)) {
                        builder.append(field.getAnnotation(ForUpdate.class).fieldName()); //获取字段名称
                        builder.append(": 【更改前:");
                        builder.append(newValue);
                        builder.append(", 更改后:");
                        builder.append(oldValue);
                        builder.append("】\n");
                    }
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
        return builder.toString();
    }
}

  • 测试
	/**
 	* @Author tianyuxu
 	* @Since 2021/3/10 16:47
 	*/
 	public class BeanUtilsTest {
 		public static void main(String[] args) {
        	Bean bean1 = Bean.builder()
                .id(1L)
                .name("name1")
                .age(10)
                .build();

       	 Bean bean2 = Bean.builder()
                .id(1L)
                .name("name2")
                .age(20)
                .build();

      	  System.out.println(BeanUtils.getChangedFields(bean1, bean2));
      	  //最终输出 :
      	  // 姓名: 【更改前:name1, 更改后:name2】
		  // 年龄: 【更改前:10, 更改后:20】
   	 	}	
 	}

总结

如上所述,我们利用泛型和反射实现了一个可以比较两个Bean实例的工具类。现在,如果有一个新的需求,要我们也记录Bean2这个类的实例变化,我们只需要在Bean2的成员变量上加上注解@ForUpdate, 然后直接调用工具类BeanUtils的getChangedFields()方法即可。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值