閱讀Spring Frameworks源碼的思考

轉(zhuǎn)載請(qǐng)注明出處即可瞒斩。
這不是一篇講Spring源碼解析的文章,也不是剖析Spring內(nèi)部設(shè)計(jì)的文章篷扩。只是在閱讀中的一些思考稠氮。

一曹阔、為什么很多優(yōu)秀框架或系統(tǒng)源碼感覺難以閱讀或理解

(1) 時(shí)間的考驗(yàn)

??任何優(yōu)秀的框架、系統(tǒng)和編程語言等都是經(jīng)歷了很長時(shí)間的考驗(yàn)隔披,比如Spring 1.0的這篇距今也有14年的時(shí)間次兆。Python和Linux的出現(xiàn)也要早于utf8。這也是Python2對(duì)字符串操作一直被人詬病的原因之一锹锰。

技術(shù)發(fā)展時(shí)間

??長時(shí)間的發(fā)展也會(huì)讓最初可能簡單的邏輯芥炭,變得非常復(fù)雜。比如早期版本的Linux只有1萬多行代碼恃慧,現(xiàn)在擁有了超過3000萬行的代碼量园蝠。
代碼量對(duì)比

??正如上圖對(duì)比的那樣,隨著時(shí)間的發(fā)展痢士,優(yōu)秀項(xiàng)目的代碼量會(huì)越來越多彪薛,并且越來越復(fù)雜。導(dǎo)致如果直接去看源碼很容易抓不住重點(diǎn)怠蹂,把思維淹沒在各種細(xì)節(jié)之中不能自拔善延。

??但是無論版本功能如何迭代,最初的核心設(shè)計(jì)思想是不會(huì)進(jìn)行變化的城侧。比如Linux 0.11就有了進(jìn)程易遣。Python Flask的路由和始終和早期版本的實(shí)現(xiàn)幾乎一樣沒有變化。所以如果直接打開Spring5的源碼一臉蒙圈的話嫌佑,其實(shí)可以去下載Spring早期版本的源碼去看下設(shè)計(jì)思想和原理豆茫,因?yàn)榇a量和功能的減少,更容易抓住核心設(shè)計(jì)思想屋摇,而不是和部分細(xì)節(jié)糾纏不清揩魂。

回到我們的主題Spring
spring-beans-1.2
spring-context-1.2
spring-core-1.2
因?yàn)榘姹竞芾希枰螺djar包炮温,然后在add jar到項(xiàng)目中(當(dāng)然這三個(gè)包肯定是跑不起來的火脉,還需要依賴apache和logger等其他相關(guān)的依賴包,本小節(jié)結(jié)尾會(huì)附錄老版本源碼下載地址)柒啤。

我們看下老版本的使用, 在使用上幾乎沒有變化倦挂。

Spring老版本的使用

我們?cè)诳聪?code>ApplicationContext的類圖,并和Spring5的做一個(gè)對(duì)比
Spring 1.2類圖

Spring 5類圖

當(dāng)然還可以對(duì)比下類的數(shù)量白修,Spring 1.2的也會(huì)少很多, 但核心的接口也都在妒峦。

BeanDefinition

XmlBeanDefinitionReader

讀到這里,如果陷入了Spring5源碼的泥潭不得主線兵睛,那么推薦閱讀下老版本的源碼肯骇,去理解下早期"最核心"的那些框架思想。
Spring老版本源碼下載地址
Spring Framework-1.2源碼

(2) 因?yàn)楹唵嗡詮?fù)雜

在技術(shù)領(lǐng)域祖很,簡潔的背后一定有很復(fù)雜的邏輯笛丙。

用個(gè)支付領(lǐng)域的例子,看似簡單的支付界面假颇,背后其實(shí)擁有很復(fù)雜的邏輯胚鸯。


滴滴支付
支付系統(tǒng)架構(gòu)

Linux系統(tǒng)雖然3000W+的代碼量,但系統(tǒng)調(diào)用依然維持在200+的數(shù)量笨鸡,而MacOS的系統(tǒng)調(diào)用還不到200。JVM的指令也在200+敌土。

Spring其實(shí)也一樣算吩,ApplicationContext的方法雖然不多,但擁有很長的繼承鏈辙浑,和很多技術(shù)細(xì)節(jié)。


ApplicationContext

所以使用起來很簡單的東西拟糕,其內(nèi)部為了簡化外部的使用判呕,會(huì)做很多封裝。但是無需被背后復(fù)雜的邏輯阻斷源碼閱讀的進(jìn)程送滞,還是有一些其他手段來解決對(duì)繁雜代碼的理解侠草。

(3) 一團(tuán)漿糊

??閱讀源碼的時(shí),經(jīng)常會(huì)發(fā)現(xiàn)看的細(xì)節(jié)越來越多犁嗅,越往后就可能記不清楚前面的邏輯边涕。這個(gè)是十分正常的現(xiàn)象。因?yàn)樵谌说拇竽X進(jìn)行記憶并進(jìn)行分析的特征(機(jī)器學(xué)習(xí)里面的概念愧哟,也可以叫做屬性)是有限的奥吩。


??當(dāng)特征(體重、翼展等)數(shù)量不是很多時(shí)蕊梧,相關(guān)專家可以根據(jù)在腦海中記憶的經(jīng)驗(yàn)霞赫,來判斷當(dāng)前鳥屬于哪個(gè)種屬。專家系統(tǒng)的作用也是類似肥矢,有專門對(duì)這些特征處理端衰,判斷"經(jīng)驗(yàn)",來確定種屬甘改。但是當(dāng)特征數(shù)很多旅东,比如上萬個(gè)特征,數(shù)十萬的特征時(shí)十艾,人腦遠(yuǎn)不能處理這么海量的數(shù)據(jù)抵代,更不用說去分析了。所以這個(gè)時(shí)候忘嫉,機(jī)器學(xué)習(xí)和深度學(xué)習(xí)就起到了它們應(yīng)有的作用荤牍。

??在閱讀源碼時(shí),一般會(huì)通過記憶庆冕,然后理清順序的執(zhí)行流程康吵,然后加上之前的記憶整理和分析,得出某個(gè)功能的實(shí)現(xiàn)邏輯或者設(shè)計(jì)思想访递。但是如果在閱讀鏈路比較長的情況下晦嵌,找不到分析的切入點(diǎn)是很正常的情況,甚至在后續(xù)的閱讀中導(dǎo)致前面的記憶開始模糊不清。在這種情況下惭载,硬著頭皮記筆記旱函,畫類圖是解決記憶模糊和簡化理解的方式之一。

??當(dāng)然還可以換一種方式去理解源碼棕兼,比如陡舅,將理解源碼的過程分為兩步,第一, Spring 對(duì)外提供的接口伴挚,包含了哪些功能, 并且這些功能上有什么分類(不是ioc, aop這種分類,后面小節(jié)會(huì)詳述)灾炭。第二, 將第一步分類后的接口茎芋,去查看繼承鏈和引用關(guān)系,控制只在一個(gè)分類中進(jìn)行閱讀, 降低整體功能多導(dǎo)致的記憶蜈出、理解田弥、分析的問題。當(dāng)然如果還可以繼續(xù)分類的話铡原,還可以進(jìn)一步降低閱讀的難度偷厦。
??如果在從某一個(gè)方法調(diào)用開始打斷點(diǎn)后,一直往下讀燕刻,讀不懂的話只泼,可以試試這個(gè)方式。并且不用擔(dān)心會(huì)丟失整體的邏輯卵洗。因?yàn)樗械募夹g(shù)都是某種組合请唱。這意味著任何具體技術(shù)都是由當(dāng)下的部件、集成件或系統(tǒng)組件構(gòu)建或組合而成的过蹂。其次十绑,技術(shù)的每個(gè)組件自身也是微縮的技術(shù)。

(4) 明白了執(zhí)行過程酷勺,但感覺沒抓住設(shè)計(jì)思想

借用《如何閱讀一本書》里面的閱讀層次劃分本橙,閱讀源碼的也應(yīng)該有四個(gè)層次,可以對(duì)標(biāo)下自己的源碼理解在哪個(gè)層次脆诉。

a. 基礎(chǔ)閱讀

在這個(gè)層次甚亭,應(yīng)該可以熟練的編寫Java代碼,并且熟悉常用的類库说,反射狂鞋,動(dòng)態(tài)搭理、設(shè)計(jì)模式潜的,面向?qū)ο蟮脑O(shè)計(jì)思想等相關(guān)內(nèi)容骚揍。這些是閱讀Spring Frameworks的必備知識(shí),否則很容易知其然不知所以然。比如大家都看過NBA信不,但是不同人看到的NBA是不同的嘲叔,比如一個(gè)妙傳,大部分人都認(rèn)為是好球抽活,但是在教練看來就可能是某種戰(zhàn)術(shù)的成功硫戈。在球員的眼里也不一樣。


曼巴精神

這本書在微信閱讀里面有中文版下硕。

b. 檢視閱讀

檢視閱讀是系統(tǒng)化略讀的一門藝術(shù)丁逝。在這個(gè)階段,也是建立橫向邏輯(后續(xù)小節(jié)會(huì)詳述)的一個(gè)過程梭姓。需要能找到相對(duì)獨(dú)立的模塊霜幼,并且找到模塊與模塊之間的關(guān)聯(lián)關(guān)系。這里不進(jìn)行詳述誉尖,后面再說罪既。

c. 分析閱讀

分析閱讀是指,一直要讀到對(duì)整個(gè)源碼深刻的理解铡恕。既能理解整體架構(gòu)琢感,又能理解核心技術(shù)細(xì)節(jié)。當(dāng)然在閱讀的過程中可能會(huì)有疑惑探熔,這個(gè)在后續(xù)章節(jié)會(huì)描述解決疑惑的方法驹针。

d. 主題閱讀

主題閱讀也叫做比較閱讀,也就是說需要閱讀其他的類似的框架源碼祭刚,并不只是Spring牌捷。不僅僅要能列出不同框架的相關(guān)之處,也能對(duì)不同框架優(yōu)缺點(diǎn)有深刻的理解涡驮。藝術(shù)書并不能保證你閱讀之后成為藝術(shù)家暗甥,只能告訴你其他藝術(shù)家用過的工具、技術(shù)和思維過程捉捅。當(dāng)然閱讀Spring也不能擔(dān)保成為好的軟件工程師撤防。但主題閱讀的這個(gè)階段,就已經(jīng)是對(duì)原理和思想內(nèi)化的過程棒口,也是整個(gè)源碼閱讀中最有收貨的寄月。因?yàn)楂@益良多,所以絕對(duì)值得花時(shí)間去努力做到這個(gè)層次无牵。

(5) 好代碼潛規(guī)則

??整潔的代碼簡單直接漾肮。整潔的代碼如同優(yōu)美的散文。整潔的代碼從不隱藏設(shè)計(jì)者的意圖茎毁,充滿了干凈利落的抽象和直截了當(dāng)?shù)目刂普Z句克懊。
??好的代碼是一種藝術(shù)忱辅,Spring更是如此。雖然代碼量相對(duì)較大谭溉,但Spring依然保持了十分整潔的代碼墙懂。比如所以類和方法的命名都有其正確的意義。就算單獨(dú)的一個(gè)方法名看不出來含義扮念。上下邏輯中依然保持了足夠的上下文用于理解损搬。并且函數(shù)的"擺放"位置也十分的"考究"。
SimpleAliasRegistry為例(在不考慮setter和getter的情況下)
方法checkForAliasCircle一定在文件最后一個(gè)調(diào)用方法的下面柜与。

SimpleAliasRegistry

registerAlias, resolveAliases兩個(gè)方法都調(diào)用了checkForAliasCircle但由于在文件中最后一個(gè)調(diào)用巧勤,所以放在了resolveAliases的后面。

二旅挤、如何在閱讀源碼過程中建立邏輯

(1) 什么是邏輯

??邏輯是指把源碼的理解組織起來踢关,這個(gè)也是達(dá)到檢視閱讀和分析閱讀的必要步驟。邏輯分為兩個(gè)分類粘茄。縱向邏輯是指開發(fā)都能看懂的因果關(guān)系秕脓。因?yàn)锳柒瓣,所以B, 因?yàn)锽吠架, 所以C芙贫。橫向邏輯是指開發(fā)能看懂的總分關(guān)系,沒有遺漏和重復(fù)傍药。A包括B和C磺平。


邏輯

(2) 縱向邏輯

縱向邏輯是指,因?yàn)锳所以B拐辽,既達(dá)到某個(gè)源碼細(xì)節(jié)(方法, 類)的邏輯達(dá)到可以理解的地步拣挪。
縱向邏輯薄弱一般有三個(gè)原因。

a. 前提條件不同

前提條件不同

雖然是因?yàn)锳俱诸,所以B菠劝,但是還有A', A''等隱含條件。
比如下面這段代碼


示例代碼

睁搭,

通過這個(gè)可以說ApplicationContext接口的實(shí)現(xiàn)類提供了通過通配符讀取Resource數(shù)組的功能(這個(gè)是錯(cuò)誤的說法)赶诊。看到這里就算沒有讀過源碼的人可能在想了"真的是這樣嗎?" 得出這樣錯(cuò)誤的結(jié)論是因?yàn)楹鲆暳说讓訉?shí)現(xiàn)的隱含條件园骆,導(dǎo)致了縱向邏輯薄弱或者直接導(dǎo)致邏輯錯(cuò)誤舔痪。

ResourceLoader

實(shí)際ApplicationContext并沒有親力親為,而是委托給了PathMatchingResourcePatternResolver锌唾。

b. 把不同性質(zhì)的東西混為一談

把不同性質(zhì)的東西混為一談

這里用分布式里面的經(jīng)吵耄混淆的一個(gè)問題來說明。筆者所在的技術(shù)群,某個(gè)群友說分布式系統(tǒng)就是在CAP下進(jìn)行權(quán)衡巍耗。且不說這句話對(duì)還是不對(duì)秋麸。這句話其實(shí)混淆了分布式系統(tǒng)的概念和分布式系統(tǒng)的問題。導(dǎo)致了這句話不太經(jīng)得起推敲炬太。首先分布式系統(tǒng)的概念是指 若干獨(dú)立計(jì)算機(jī)的集合灸蟆,這些計(jì)算機(jī)對(duì)于"用戶"來說就像是單個(gè)相關(guān)系統(tǒng)。一致性其實(shí)是在分布式系統(tǒng)理論中要解決的問題亲族。那么一致性問題的解決炒考,其實(shí)不僅僅包含著CAP和BASE等基礎(chǔ)理論,還需要考慮從以數(shù)據(jù)為中心的一致性模型和以用戶為中心的一致性模型霎迫。以數(shù)據(jù)為中心的斋枢,還包含了嚴(yán)格一致性、順序一致性等知给。以用戶為中心的包含了單調(diào)讀瓤帚,單調(diào)寫等。

c. 硬套邏輯

在Linux中在用戶空間可以通過nice命令設(shè)置進(jìn)程的靜態(tài)優(yōu)先級(jí)涩赢,這在內(nèi)部會(huì)調(diào)用nice系統(tǒng)調(diào)用戈次。進(jìn)程nice值在-20和+19之間。這是一個(gè)被歷史淹沒的詭異的范圍筒扒。那么根據(jù)這個(gè)怯邪,我就可以說,當(dāng)時(shí)作者的年齡是20花墩,她女朋友年齡19悬秉,所以有了這么一個(gè)詭異的范圍。當(dāng)然我肯定是在胡扯冰蘑,所以和泌,沒有邏輯的時(shí)候就不要硬去套一個(gè)縱向邏輯了。

(3) 橫向邏輯

總分關(guān)系比較好理解懂缕,在源碼閱讀來說其實(shí)就是在區(qū)分模塊(分類)來進(jìn)行閱讀

ApplicationContext

ApplicationContext通過繼承如圖的接口來擴(kuò)展自身的功能允跑,那么就可以把這些接口根據(jù)一定規(guī)則進(jìn)行分模塊,分別來進(jìn)行閱讀搪柑,降低整體的閱讀復(fù)雜度聋丝。

(4) 金字塔邏輯

把橫向邏輯和縱向邏輯形成金字塔結(jié)構(gòu)的話,如下圖工碾,我相信至少已經(jīng)達(dá)到了分析閱讀的層次了弱睦。


金字塔邏輯

三、如何解決在閱讀過程中的疑惑

在閱讀過程中肯定會(huì)有疑惑的地方渊额,在這里先說一個(gè)小故事况木,因明是古印度的邏輯學(xué)垒拢,提倡因明立量,最常見的三種量, 現(xiàn)量: 用事實(shí)證明; 比量: 用邏輯推論; 圣言量: 圣人所說火惊。當(dāng)年玄奘西行求法就曾深入學(xué)習(xí)過《因明》求类。因?yàn)槟菚r(shí)候辨經(jīng)幾乎都是賭命的。輸了可能要跳火山口的屹耐。在源碼閱讀的過程中尸疆,也可以理解為是源碼作者在透過源碼,在跟我們對(duì)話惶岭。那么遇到不理解的地方寿弱,或者有疑惑的地方,也可以通過現(xiàn)量的方式按灶,比如某個(gè)方法的調(diào)用邏輯和實(shí)現(xiàn)的功能通過方法名稱無法理解症革。那么就可以直接在往源碼下層去閱讀,甚至直接讀到JDK里面的類鸯旁。比量的話噪矛,其實(shí)就可以利用前面所講到過的兩個(gè)方向的邏輯思維。

當(dāng)然如果通過現(xiàn)量和比量還是無法理解的話铺罢,建議采取逆向思維摩疑,想一想,如果不這么設(shè)計(jì)和實(shí)現(xiàn)畏铆,會(huì)怎么樣^_^

還有可能有些實(shí)現(xiàn)細(xì)節(jié)一直在困擾著你吉殃,這時(shí)辞居,除了求人,求百度Google以外蛋勺。建議可以先放下瓦灶,先把整體框架理解了再說。把不理解的地方記錄下來抱完。就算現(xiàn)在不理解贼陶,沒人能解答,可能過幾年經(jīng)驗(yàn)豐富了巧娱,就已經(jīng)有了答案了碉怔。人生的所有問題,總會(huì)有一個(gè)答案的禁添。

四撮胧、閱讀的Spring源碼的切入點(diǎn)

經(jīng)過上面的巴拉巴拉的一大堆,其實(shí)就已經(jīng)隱含了閱讀源碼的切入點(diǎn)ApplicationContext了老翘。需要先通過橫向邏輯研究對(duì)外提供的功能和內(nèi)部實(shí)現(xiàn)進(jìn)行分類芹啥,然后在每一個(gè)小模塊把實(shí)現(xiàn)原理研究清楚锻离,并且如果模塊功能還是很繁雜,依然可以再次進(jìn)行分類墓怀,直到理解為止汽纠。在每個(gè)模塊內(nèi)部在通過縱向邏輯,把執(zhí)行的流程理清傀履。在這個(gè)過程無論是通過畫圖也好虱朵,還是何種方式,只要能方便記憶和理解的都是好貓啤呼。

五卧秘、結(jié)束語

后續(xù)打算通過前面說的邏輯思維來整理Spring Frameworks的部分源碼。幫助讀者達(dá)到分析閱讀的層次(其實(shí)是在幫我自己官扣,虛榮一把)翅敌。
下篇可能會(huì)先說Resource的相關(guān)實(shí)現(xiàn)內(nèi)容,也有可能去看看K8s的Schedule惕蹄。平時(shí)工作略忙蚯涮,不定期更新,盡量至少一周一篇卖陵。
路還很長遭顶,要想達(dá)到確保系統(tǒng)在整體上能夠從任何未曾預(yù)料到的重創(chuàng)中恢復(fù)過來,還有很長的路要走泪蔫。

參考

https://spring.io/
https://github.com/spring-projects/spring-framework
《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》
《技術(shù)的本質(zhì)》
《Spring揭秘》
《Spring深度源碼解析》
《如何閱讀一本書》
《行者玄奘》
《代碼整潔之道》
《精準(zhǔn)表達(dá)》
《軟件架構(gòu)》
《架構(gòu)寶典》
《恰如其分的軟件架構(gòu)》
《The Mamba Mentality: How I Play》
《發(fā)布棒旗!設(shè)計(jì)與部署穩(wěn)定的分布式系統(tǒng)》
《分布式系統(tǒng)原理與泛型 第二版》
《持續(xù)演進(jìn)的Cloud Native:云原生架構(gòu)下微服務(wù)最佳實(shí)踐》
《大規(guī)模分布式存儲(chǔ)系統(tǒng):原理解析與架構(gòu)實(shí)戰(zhàn)》
《深入Linux內(nèi)核架構(gòu)》
都是好書, kindle商店買一波

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撩荣,隨后出現(xiàn)的幾起案子铣揉,更是在濱河造成了極大的恐慌,老刑警劉巖餐曹,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逛拱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡台猴,警方通過查閱死者的電腦和手機(jī)朽合,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饱狂,“玉大人曹步,你說我怎么就攤上這事∥斯伲” “怎么了箭窜?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衍腥。 經(jīng)常有香客問我磺樱,道長纳猫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任竹捉,我火速辦了婚禮芜辕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘块差。我一直安慰自己侵续,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布憨闰。 她就那樣靜靜地躺著状蜗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹉动。 梳的紋絲不亂的頭發(fā)上轧坎,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音泽示,去河邊找鬼缸血。 笑死,一個(gè)胖子當(dāng)著我的面吹牛械筛,可吹牛的內(nèi)容都是我干的捎泻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼埋哟,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼笆豁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赤赊,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤渔呵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后砍鸠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耕驰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年爷辱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朦肘。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饭弓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出媒抠,到底是詐尸還是另有隱情弟断,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布趴生,位于F島的核電站阀趴,受9級(jí)特大地震影響昏翰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刘急,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一棚菊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叔汁,春花似錦统求、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至另假,卻和暖如春像屋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浪谴。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工开睡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人苟耻。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓篇恒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凶杖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胁艰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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