首先交代背景,前幾天遇到一個小bug,因爲其餘系統的一個DTO子類和父類有一個字段名重複了,因此致使我set的子類字段那邊拿不到值。改起來很簡單嘛,讓對面把子類的字段刪掉就好,可是拿不到值的緣由讓我想了好久,很明顯是序列化和反序列化的過程當中這個字段的值丟失了,可是究竟是在哪一步呢?仍是決定看看源碼給本身一個答案。java
首先先肯定協議和序列化的方式:apache
<dubbo:protocol name="dubbo" port="${dubbo.port}" host="${dubbo.host}"/>
ok,dubbo協議,沒有配序列化方式,那再來找一下dubbo默認的序列化方式:
首先找到了這個包:
數組
而後在Serialization接口(實現一些自定義序列化擴展用的)中發現了默認序列化的方式是hessian2spa
而後經過Hessian2Serialization的serialize方法和deserialize方法找到了Hessian2ObjectOutput、Hessian2ObjectInput這個兩個類,以後經過裏面的writeObject方法和readObject方法,找到了這兩個類:JavaSerializer和JavaDeserializer。就是默認的序列化器和反序列化器。debug
首先咱們來看序列化:
構造方法:
code
咱們看看他幹了個什麼事
首先檢查了有沒有writeReplace方法
而後把全部聲明的字段放到數組中遍歷,而後把除了transient和static修飾的字段放到ArrayList中去
而後往上找父類執行相同操做
而後把全部符合條件的字段放到一個Field數組裏面,先放基本數據類型,再放引用數據類型
最後把字段放入對應類型的序列化器中去
獲得一個FieldSerializer序列化器數組xml
咱們仍是繼續看writeObject方法接口
主要是第二張圖的3個方法,作的事情大概就是循環序列化field的名和值ip
下面再來看看反序列化:
構造方法:文檔
這裏大概作了3個事
獲取fieldMap,方法以下:
獲取readResolve方法
獲取全部構造器
遍歷構造器數組找到cost最小的最佳構造器
而後用最佳構造器進行構造,方法以下:
先看構造器方法,基本數據類型的話返回包裝類型,引用數據類型返回null
主要咱們來看獲取fieldMap的時候。和序列化時相同,先取子類再取父類,原本覺得到這就結束了,但是看到了一行校驗
fieldMap.get(field.getName()) == null
若是父類的字段名和子類字段名相同,會跳過該循環,也就是說只會有子類的值,那爲何還會覆蓋?
看最後一個readMap方法:
debug發現值被覆蓋就是在這裏操做的
deser.deserialize(in, obj);
子類set過值之後,父類過來也會拿到子類的反序列化器,把子類的值覆蓋掉。
最後,那爲何會到readMap這一步呢?
debug發現SerializerFactory拿到反序列化器後會執行一個readMap操做
基本上就到這裏了,最主要的緣由仍是readMap方法,並非不少博文說的fieldMap。若是哪裏有不對的地方歡迎指出、討論以便及時修改。
參考文檔:連接描述