轉至:https://chenzhihao.cc/archives/526
異常現(xiàn)象
在使用Springboot 配合 Redis做緩存處理的時候贪嫂,單元測試中對象的序列化和反序列化操作均正常,但是項目Runing后场航,接口操作出現(xiàn)類型轉換異常果港,最可笑的是同一類型轉換出了錯??。
java.lang.ClassCastException: OauthCodeRedisCacheEntity cannot be cast to OauthCodeRedisCacheEntity
解決思路
第一、我排查了一下單元測試和實際API接口的代碼邏輯是否相同费奸,然而是相同的弥激。
第二、通過Debug模式檢查了一下單元測試和實際API接口對本系統(tǒng)下Redis反序列化方法入參的參數值愿阐,發(fā)現(xiàn)也均值一樣的
第三微服、先后執(zhí)行單元測試和實際API,查看Redis緩存中的數據是否相同缨历,經檢驗也是相同的以蕴。
第四、我考慮到是否是因多線程引起的辛孵,所以對調用該序列化方法的Service層進行了并發(fā)控制丛肮,這里僅加了可重入鎖。然而并沒有成功
第五魄缚、MDZZ宝与,心態(tài)爆炸,歇了一會冶匹,和丫頭說了會話 …. 很開心
第六伴鳖、Google 搜索關鍵詞“Springboot Redis 反序列化類型轉換失敗” …. 未果,看來中文search不行
第七徙硅、Google 直接粘貼報錯信息。 果然搞疗,SF大法好
刨根問底
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社區(qū)一大佬就此問題的回答嗓蘑,大意是說,當使用SpringBoot 的 DevTools時匿乃,其實該工具是具有緩存效果的桩皿,這點需要注意,而且該大佬也提供的注意事項的連接地址 this limitation.
當對象被序列化到緩存里時幢炸,當前應用的類加載器是C1泄隔,當你改變了一些代碼或者配置文件的時候,DevTools 工具將會自動重新啟動這個容器宛徊,并且創(chuàng)建一個新的類加載器 C2. 這時候調用這個具有緩存的方法時佛嬉,緩存管理將會從緩存里找到該條緩存記錄并進行反序列化操作。如果緩存庫不考慮上下文的話闸天,也就是沒注意到類加載器的變化時暖呕,該對象將會有錯誤的類加載器(這解釋了奇怪的異常)。
其實就是因上下文類加載器不同而產生這樣的錯誤苞氮,那么歸根結底就是因SpringBoot DevTools工具搞的鬼湾揽。
果然,在項目配置初期,為了實現(xiàn)所謂的熱部署和熱加載使用了該工具庫库物,果斷刪掉霸旗。
Perfect!戚揭!
總結
但凡遇到報錯信息诱告,切記不要慌不要亂,有因才有果毫目,可以嚇你根據自己的分析按照自己的想法進行錯誤排查蔬啡,針對出現(xiàn)的類型轉換出現(xiàn)的異常,首先應該想到是不是自己代碼的問題镀虐,因為此次錯誤我在單元測試中是可用的箱蟆,所以業(yè)務代碼層面不會出現(xiàn)問題。
盡量把自己能想到 的解決方式全都用一遍刮便,因為此時你對這個報錯已經有了大題的了解空猜,這個了解僅僅是利用排除法了解到的,即 他不是因為什么什么而發(fā)生恨旱。所以在接下來使用搜索引擎的時候辈毯,可以避免走一些彎路。
自己能想到的解決方法都用了之后搜贤,建議直接Google 報錯信息谆沃,簡單粗暴。逐條查看仪芒,按照說明處理唁影。
當然最重要的還是心態(tài),我在掏空自己的想法之后掂名,果斷選擇去和小迷妹聊會天据沈,解放一下思路,放松一下緊繃的神經饺蔑。當然锌介,在放松之余,我也在想這個問題猾警,只是會更放松孔祸。
總而言之,言而總之肿嘲,所有的程序員們融击,當你寫代碼遇到問題遇到Bug,請找你的女神聊會天v摺W鹄恕匣屡!