概述
RedisTemplate序列化后数据字段增加
- 缺陷案例
- 源码解析
- 总结
缺陷案例
RedisTemplate应该很多公司都有在用,这次发现一个小问题,对象序列化后,缓存到redis的json数据,出现了一个多余的字段。给我一顿找啊。
检查了一下缓存数据对象信息,确认无误。(为什么需要检查这个呢,因为之前吃过亏,使用Lambda表达式的双大括号创建的对象{{}},class信息会指向当前类,而不是对应的Bean,进而反序列化失败)再找到对应的类,向着父类一层一层的找,确实没有这个update字段。(是的,序列化对象多出来了一个update字段,布尔类型,而且值为false)
虽然,没有找到该类以及其所有父类中又布尔类型的update字段,但有一个方法,却让我分外怀疑。
public Boolean isUpdate(){
return !Objects.isNull(this.id) && this.id > 0;
}
但,方法会序列化?
由于使用该基础方法的地方较多,也为了减少代码的修改,我试着添加了Transient注解,是的,这个注解还能添加到方法上**(我之前只知道它能修饰字段,不让字段序列化)**。这个地方还踩了个坑,添加@Transient注解时,由于之前有同事已经在该类中使用过,所以没有让我选择哪种依赖。导致第一次测试没成功,走了些弯路。
之前引入的依赖为org.springframework.data.annotation.Transient
,改了后生效的依赖为java.beans.Transient
。
上述方法改后为
@java.beans.Transient
public Boolean isUpdate(){
return !Objects.isNull(this.id) && this.id > 0;
}
经测试,重新缓存到redis序列化数据,没有多余的字段。
isUpdate,是不是特别想update自动生成的getter?确实,网上搜了一下,发现也有人遇到过使用getxxx方法,序列化后多出xxx属性的情况。
源码解析
带着疑问,从RedisTemplate的set方法一路网上找,找到了org.springframework.data.redis.serializer.RedisSerializer#serialize
接口。该接口有许多实现,似乎最终都指向了com.alibaba.fastjson.support.spring.FastJsonRedisSerializer#serialize
fastJson的实现方式,顺着继续网上找,遇到了一些代码阅读的阻碍,毕竟大海捞针。
将编辑窗口停留在FastJsonRedisSerializer,点击左上角箭头指向的按钮,定位到依赖中该类的位置
接着,找到fastJson最外层的依赖目录,右键–>find in path,搜索"is",你们猜我找到了啥。
正如大家所见,找到了com.alibaba.fastjson.util.TypeUtils类中,有关于我们想要的逻辑。
1.2.69版本,is开头的方法判断在2041行,对应的,get开头的方法判断在1942行。剩下的,就让大家自己去看吧,逻辑清晰明了了。
总结
- 布尔类型的字段,最好不要定义为is开头,在反射或者某些框架的逻辑里面可能会有未知的异常。使用Lombok
@Data
生成的getter,会是getIsXXX,已经比较友好了,但还是要尽量规避。 - 针对自定义的is和get开头的方法,我相信基本都是不需要序列化,也很少会涉及到序列化,可以试着添加@Transient注解,解决没必要的烦恼。
最后
以上就是坦率月饼为你收集整理的RedisTemplate序列化后数据字段增加,代码无常,大肠包小肠的全部内容,希望文章能够帮你解决RedisTemplate序列化后数据字段增加,代码无常,大肠包小肠所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复