转至:www.jianshu.com/p/b7635b08a…
异常现象
在使用Springboot 配合 Redis做缓存处理的时候,单元测试中对象的序列化和反序列化操作均正常,但是项目Runing后,接口操作出现类型转换异常,最可笑的是同一类型转换出了错。

排查思路
1.首先根据错误信息看出redis中是获取到数据的,不然就不会是转换异常;验证:客户端工具连接到redis服务器根据key获取到value;
2.查看配置序列化和反序列化实现类

value为对象时配置JdkSerializationRedisSerializer,没有问题。
3.跟踪源码 JdkSerializationRedisSerializer 源码反序列化实现DefaultDeserializer

到上面这一步是有值的,也就是说已经反序列化为java对象了,到这里原因失败的原因已经出来了,两个相同类型的类转换失败,大概率是有不同的类加载器加载的。
解决方法
When you use DevTools with caching, you need to be aware of this limitation.
When the object is serialized into the cache, the application class loader is C1.
Then after you change some code/configuration, devtools automatically restart the context and creates a new classloader (C2).
When you hit that cache method, the cache abstraction finds an entry in the cache and it deserializes it from the store.
If the cache library doesn’t take the context classloader into account,
that object will have the wrong classloader attached to it (which explains that weird exception A cannot be cast to A).上面这段话是Stack Overflow社区一大佬就此问题的回答,大意是说,当使用SpringBoot 的 DevTools时,其实该工具是具有缓存效果的,这点需要注意,而且该大佬也提供的注意事项的连接地址 this limitation.
当对象被序列化到缓存里时,当前应用的类加载器是C1,当你改变了一些代码或者配置文件的时候,DevTools 工具将会自动重新启动这个容器,并且创建一个新的类加载器 C2. 这时候调用这个具有缓存的方法时,缓存管理将会从缓存里找到该条缓存记录并进行反序列化操作。如果缓存库不考虑上下文的话,也就是没注意到类加载器的变化时,该对象将会有错误的类加载器(这解释了奇怪的异常)。
其实就是因上下文类加载器不同而产生这样的错误,那么归根结底就是因SpringBoot DevTools工具搞的鬼。