06 | Android 高級(jí)進(jìn)階(源碼剖析篇) Twitter 的高性能序列化框架 Serial(二)

作者簡(jiǎn)介:ASCE1885, 《Android 高級(jí)進(jìn)階》作者。
本文由于潛在的商業(yè)目的涡上,未經(jīng)授權(quán)不開(kāi)放全文轉(zhuǎn)載許可,謝謝拒名!
本文分析的源碼版本已經(jīng) fork 到我的 Github吩愧。

0eb640f81a22914b061abb61abe3e677aa03328389jpg.jpg

通過(guò)前面一篇文章的介紹,我們知道 Serial 框架的核心是 Serializer 類(lèi)增显,對(duì)象的序列化和反序列化都是通過(guò)重寫(xiě)這個(gè)類(lèi)的方法實(shí)現(xiàn)的雁佳,因此我們就以 Serializer 類(lèi)為起點(diǎn)來(lái)開(kāi)始源碼的剖析,首先來(lái)看下這個(gè)類(lèi)的繼承體系:

讀過(guò)前面一篇文章的同學(xué)對(duì)這幾個(gè)類(lèi)應(yīng)該都有印象同云,這里再簡(jiǎn)單總結(jié)一下:

  • Serializer:抽象基類(lèi)糖权,一切的開(kāi)始
  • ObjectSerializer:通過(guò)在序列化時(shí)增加版本號(hào)信息從而提供向后兼容性
  • BuilderSerializer:繼承自 ObjectSerializer,支持在反序列化時(shí)通過(guò) Builder 模式構(gòu)造對(duì)象
  • ValueSerializer:不包含版本號(hào)信息炸站,只處理簡(jiǎn)單數(shù)據(jù)類(lèi)型星澳,不考慮向后兼容性

同時(shí),為了讓框架使用者少寫(xiě)樣板代碼旱易,Serial 還提供 CoreSerializers 和 CollectionSerializers 兩個(gè)類(lèi)禁偎,分別針對(duì)常用的數(shù)據(jù)類(lèi)型和集合定義了一系列默認(rèn) Serializer 類(lèi)。下面我們來(lái)一一分析咒唆。

Serializer

所有 Serializer 的抽象基類(lèi)届垫,定義了最基礎(chǔ)的序列化和反序列化整體框架,我們直接來(lái)看代碼和注釋?zhuān)?/p>

public abstract class Serializer<T> {
    /**
     * 序列化方法
     * @param context 序列化上下文信息
     * @param output 序列化輸出流
     * @param object 要序列化的對(duì)象實(shí)例
     * @throws IOException
     */
    public abstract void serialize(@NotNull SerializationContext context,
            @NotNull SerializerOutput output, @Nullable T object) throws IOException;

    /**
     * 反序列化方法全释,反序列化后生成的對(duì)象可能為空
     * @param context 序列化上下文信息
     * @param input 序列化輸入流
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Nullable
    public abstract T deserialize(@NotNull SerializationContext context,
            @NotNull SerializerInput input) throws IOException, ClassNotFoundException;

    /**
     * 當(dāng)反序列化后生成的對(duì)象為空時(shí)將拋出異常
     * @param context 序列化上下文信息
     * @param input 序列化輸入流
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @NotNull
    public final T deserializeNotNull(@NotNull SerializationContext context,
            @NotNull SerializerInput input) throws IOException, ClassNotFoundException {
        final T deserializedObject = deserialize(context, input);
        return InternalSerialUtils.checkIsNotNull(deserializedObject);
    }
}

其中涉及到其他幾個(gè)重要的類(lèi):

  • SerializationContext:序列化相關(guān)上下文信息装处,下面會(huì)進(jìn)一步介紹
  • SerializerInput:序列化輸入流,從序列化后的數(shù)據(jù)中讀取指定類(lèi)型信息的通道,反序列化時(shí)使用妄迁,我們將會(huì)在下一篇文章集中介紹寝蹈,在這里讀者只需要理解它的作用就行
  • SerializerOutput:序列化輸出流,將對(duì)象指定類(lèi)型屬性信息寫(xiě)入到其他介質(zhì)(磁盤(pán)等)中的通道登淘,序列化時(shí)使用箫老,同樣會(huì)在下一篇文章介紹

SerializationContext 用于保存序列化過(guò)程中的環(huán)境信息,目前提供兩個(gè)方法分別來(lái)判斷當(dāng)前是開(kāi)發(fā)環(huán)境和線(xiàn)上發(fā)布環(huán)境黔州,同時(shí)提供一個(gè)默認(rèn)的實(shí)現(xiàn)類(lèi)耍鬓,代碼如下:

public interface SerializationContext {

    /**
     * 線(xiàn)上發(fā)布環(huán)境下的默認(rèn)實(shí)現(xiàn)
     */
    SerializationContext ALWAYS_RELEASE = new SerializationContext() {
        @Override
        public boolean isDebug() {
            return false;
        }

        @Override
        public boolean isRelease() {
            return true;
        }
    };

    /**
     * 返回 true 表示當(dāng)前是開(kāi)發(fā)環(huán)境,某些序列化和反序列化操作會(huì)被執(zhí)行(例如調(diào)試信息的保存)
     * @return
     */
    boolean isDebug();

    /**
     * 返回 true 表示當(dāng)前是線(xiàn)上發(fā)布環(huán)境
     * @return
     */
    boolean isRelease();
}

可以看到流妻,isDebug 和 isRelease 本質(zhì)上是互斥的牲蜀,因此,更好的實(shí)現(xiàn)是保留一個(gè)即可绅这,沒(méi)必要在增加復(fù)雜度的情況下沒(méi)有得到其他任何好處涣达。當(dāng)然,隨著后面框架的迭代升級(jí)证薇,SerializationContext 可能會(huì)增加更多其他的環(huán)境上下文相關(guān)信息度苔。

讓我們回到 Serializer 類(lèi)的實(shí)現(xiàn)中,可以看到有兩個(gè)反序列化的方法浑度,deserialize 和 deserializeNotNull寇窑,后者是在前者執(zhí)行結(jié)果的基礎(chǔ)上增加對(duì)反序列化后對(duì)象是否為空的校驗(yàn),如果為空則拋出異常俺泣,使用者可以根據(jù)具體業(yè)務(wù)需求選用疗认,為空校驗(yàn)在 InternalSerialUtils.checkIsNotNull 方法中,代碼如下:

@NotNull
@Contract("null -> fail")
public static <T> T checkIsNotNull(@Nullable T value) {
    if (!(value != null)) {
        throw new AssertionError("Assertion failed.");
    }
    return value;
}

可以看到代碼中使用雙重否定來(lái)判斷 value 是否為空伏钠,這段代碼同樣顯得畫(huà)蛇添足横漏,直接判斷 value == null 即可。

還有 59% 的精彩內(nèi)容
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
支付 ¥5.20 繼續(xù)閱讀
  • 序言:七十年代末熟掂,一起剝皮案震驚了整個(gè)濱河市缎浇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赴肚,老刑警劉巖素跺,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異誉券,居然都是意外死亡指厌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)踊跟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)踩验,“玉大人,你說(shuō)我怎么就攤上這事』叮” “怎么了牡借?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)袭异。 經(jīng)常有香客問(wèn)我钠龙,道長(zhǎng),這世上最難降的妖魔是什么御铃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任碴里,我火速辦了婚禮,結(jié)果婚禮上畅买,老公的妹妹穿的比我還像新娘并闲。我一直安慰自己,他們只是感情好谷羞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著溜徙,像睡著了一般湃缎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蠢壹,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天嗓违,我揣著相機(jī)與錄音,去河邊找鬼图贸。 笑死蹂季,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疏日。 我是一名探鬼主播偿洁,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沟优!你這毒婦竟也來(lái)了都毒?” 一聲冷哼從身側(cè)響起蝇闭,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后铺董,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡痛倚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年咬展,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隘谣。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡增拥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情跪者,我是刑警寧澤棵帽,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站渣玲,受9級(jí)特大地震影響逗概,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忘衍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一逾苫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枚钓,春花似錦铅搓、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嫩舟,卻和暖如春氢烘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背家厌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工播玖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饭于。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓蜀踏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親掰吕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子果覆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 作者簡(jiǎn)介:ASCE1885, 《Android 高級(jí)進(jìn)階》作者畴栖。本文由于潛在的商業(yè)目的随静,未經(jīng)授權(quán)不開(kāi)放全文轉(zhuǎn)載許可...
    asce1885閱讀 1,089評(píng)論 0 24
  • JAVA序列化機(jī)制的深入研究 對(duì)象序列化的最主要的用處就是在傳遞,和保存對(duì)象(object)的時(shí)候,保證對(duì)象的完整...
    時(shí)待吾閱讀 10,837評(píng)論 0 24
  • 一、 序列化和反序列化概念 Serialization(序列化)是一種將對(duì)象以一連串的字節(jié)描述的過(guò)程吗讶;反序列化de...
    步積閱讀 1,437評(píng)論 0 10
  • 深港通開(kāi)閘燎猛!6個(gè)股賺到1400萬(wàn)多,下一只正在布局照皆! 1 深港通12月5日正式發(fā)車(chē) 又到了周一重绷,在這個(gè)周末可是發(fā)生...
    72e31abbfa15閱讀 206評(píng)論 0 0
  • 每個(gè)人的人生都有著不同的bug,或大或小膜毁,我們?cè)谶@種情況下會(huì)感到壓抑昭卓、孤獨(dú)愤钾、頹廢,慢慢地喪失了本來(lái)的自信候醒,最終一蹶...
    唐悅閱讀 295評(píng)論 -2 0