對象反序列化出現類型不匹配的情況(spring-boot-devtools)


目前在做springboot項目的shiro session redis共享功能。但是有一個對象我把它放到redis中之后再取出來就會出現類型不匹配的異常

AuthorizationUser user = (AuthorizationUser) cache.getSuper(key);

異常信息:

java.lang.ClassCastException: com.ch.evaluation.auth.shiro.entity.AuthorizationUser cannot be cast to com.ch.evaluation.auth.shiro.entity.AuthorizationUser

通過debug看到他們的類信息是一樣的

難道只是看起來一樣么?我來判斷一下

結果是false ,

那么我們知道JVM判斷兩個類對象是否相同的依據:一是類全稱;一個是類加載器

既然他倆的類全稱一樣,那么問題肯定就出在了類加載器上了

我們可以Debug看一下他倆的類加載器

果然不出所料,他倆的類加載器是不同的!

那么是什么原因導致他的類加載器不一樣呢?

  大家都知道虛擬機的默認類加載機制是通過雙親委派實現的。springboot為了實現程序動態性(比如:代碼熱替換、模塊熱部署等,白話講就是類文件修改后容器不重啟),“破壞或犧牲” 了雙親委派模型。springboot通過強行干預-- “截獲”了用戶自定義類的加載(由jvm的加載器AppClassLoader變為springboot自定義的加載器RestartClassLoader,一旦發現類路徑下有文件的修改,springboot中的spring-boot-devtools模塊會立馬丟棄原來的類文件及類加載器,重新生成新的類加載器來加載新的類文件,從而實現熱部署。比較流行的OSGI也能實現熱部署)。



既然源頭因熱部署而起,所以只要想辦法關掉springboot的熱部署即可。

<方案一>  通過卸掉springboot的熱部署模塊spring-boot-devtools來實現

在pom中注釋掉springboot的spring-boot-devtools

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
 </dependency>

<方案二>如果不想卸掉spring-boot-devtools模塊也可禁用部署功能

 
 

讀者也可以在application.properties設置禁用屬性,但它的作用域只發生在當前模塊,如果你的項目牽扯到多個模塊,最好通過上面的方式在整個運行系統的級別禁用,以免出現多個模塊之間實現類文件調用時類加載器不一致的問題。

<方案三>既然是類加載器的問題也可使用Spring的ConfigurableObjectInputStream配合Thread.currentThread().getContextClassLoader() 來使用。

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM