Java - 检测对象是否已更改/脏检测机制的框架
Java - Framework to detect if Object has changed / dirty detection mechanism
亲爱的,我目前正在实施一个 java 客户端,该客户端大量使用第三方网络服务。为了获得性能,我只想在客户端的对象被修改(变脏)的情况下调用 webservices。
不是编写一种能够检测对象是否脏的框架,而是存在任何可以重复使用且不绑定到其核心产品(例如 hibernate)的开放/通用框架?
我假设对象不是指单个标量值,而是指 bean。
从技术上讲,您可以做各种花哨的事情来检测 bean 突变,例如更改字节代码并在对象字段更新时添加一些代码。
另一种选择是保留旧 bean 实例的副本并进行比较。
所以实际上问题减少到比较两个 bean,这里被问到:how to generically compare entire java beans? 可能你会发现更多,通常有很多处理 bean 的框架。
但是,既然你调用了网络服务,你就必须有一种机制来序列化你的对象。在发送更新请求之前,您可以使用新旧对象的序列化形式来比较身份。
更改通知: 我不建议将更改侦听器附加到每个 bean。这可能会改变您的总体性能并引入内存泄漏。还有一个事务问题:如果更新了一个bean属性,那么一个bean什么时候更新完成?所以无论如何你都需要在突变之后进行显式调用。
我自己和其他缓存人员注意: 实际上这是在缓存上提供类似 Cache.putIfNotEquals(key, value) 的方法的用例,它是没有太多的努力。缓存已经存储了以前的值,如果值发生变化,它只会调用缓存写入器(在直写设置中)。
给其他人一个起点。
TestBean bean1 = new TestBean("AAA");
TestBean bean2 = new TestBean("BBB");
log.info("serialize...");
ByteArrayOutputStream str1 = new ByteArrayOutputStream();
ObjectOutputStream oos1 = new ObjectOutputStream(str1);
oos1.writeObject(bean1);
byte[] serialized1 = str1.toByteArray();
oos1.close();
ByteArrayOutputStream str2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(str2);
oos2.writeObject(bean2);
byte[] serialized2 = str2.toByteArray();
oos2.close();
log.info("compare");
boolean same = Arrays.equals(serialized1, serialized2);
这种方法的优势
- 您序列化整个对象结构,因此它支持开箱即用的复杂层次结构,您不必关心循环(父/子)
- 您可以对要从序列化/比较中排除的成员使用 "transient" 关键字
- 您不必向 bean classes 添加一些样板代码(除了 class 需要实现 Serializable 接口)
缺点
- 它不是细粒度的,所以你不会开箱即用哪些字段是脏的。使用 own serialization format
有一些复杂的方法
- 我还没有考虑过性能,但我可以想象其他方法也不是免费的,所以在这里你需要自己测试和调整方法。
亲爱的,我目前正在实施一个 java 客户端,该客户端大量使用第三方网络服务。为了获得性能,我只想在客户端的对象被修改(变脏)的情况下调用 webservices。
不是编写一种能够检测对象是否脏的框架,而是存在任何可以重复使用且不绑定到其核心产品(例如 hibernate)的开放/通用框架?
我假设对象不是指单个标量值,而是指 bean。
从技术上讲,您可以做各种花哨的事情来检测 bean 突变,例如更改字节代码并在对象字段更新时添加一些代码。
另一种选择是保留旧 bean 实例的副本并进行比较。 所以实际上问题减少到比较两个 bean,这里被问到:how to generically compare entire java beans? 可能你会发现更多,通常有很多处理 bean 的框架。
但是,既然你调用了网络服务,你就必须有一种机制来序列化你的对象。在发送更新请求之前,您可以使用新旧对象的序列化形式来比较身份。
更改通知: 我不建议将更改侦听器附加到每个 bean。这可能会改变您的总体性能并引入内存泄漏。还有一个事务问题:如果更新了一个bean属性,那么一个bean什么时候更新完成?所以无论如何你都需要在突变之后进行显式调用。
我自己和其他缓存人员注意: 实际上这是在缓存上提供类似 Cache.putIfNotEquals(key, value) 的方法的用例,它是没有太多的努力。缓存已经存储了以前的值,如果值发生变化,它只会调用缓存写入器(在直写设置中)。
给其他人一个起点。
TestBean bean1 = new TestBean("AAA");
TestBean bean2 = new TestBean("BBB");
log.info("serialize...");
ByteArrayOutputStream str1 = new ByteArrayOutputStream();
ObjectOutputStream oos1 = new ObjectOutputStream(str1);
oos1.writeObject(bean1);
byte[] serialized1 = str1.toByteArray();
oos1.close();
ByteArrayOutputStream str2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(str2);
oos2.writeObject(bean2);
byte[] serialized2 = str2.toByteArray();
oos2.close();
log.info("compare");
boolean same = Arrays.equals(serialized1, serialized2);
这种方法的优势
- 您序列化整个对象结构,因此它支持开箱即用的复杂层次结构,您不必关心循环(父/子)
- 您可以对要从序列化/比较中排除的成员使用 "transient" 关键字
- 您不必向 bean classes 添加一些样板代码(除了 class 需要实现 Serializable 接口)
缺点
- 它不是细粒度的,所以你不会开箱即用哪些字段是脏的。使用 own serialization format 有一些复杂的方法
- 我还没有考虑过性能,但我可以想象其他方法也不是免费的,所以在这里你需要自己测试和调整方法。