《Spring實(shí)戰(zhàn)》學(xué)習(xí)筆記-第一章:Spring之旅

簡(jiǎn)潔的Spring

為了降低Java開發(fā)的復(fù)雜性,Spring采取了以下4種關(guān)鍵策略:

  • 基于POJO的輕量級(jí)和最小侵入性編程瓜贾;
  • 通過依賴注入和面向接口實(shí)現(xiàn)松耦合龟劲;
  • 基于切面和慣例進(jìn)行聲明式編程答恶;
  • 通過切面和模板減少樣板式代碼裕坊。

激發(fā)POJO的潛能

相對(duì)于EJB的臃腫堰氓,Spring盡量避免因自身的api而弄亂用戶的應(yīng)用代碼,Spring不會(huì)強(qiáng)迫用戶實(shí)現(xiàn)Spring規(guī)范的接口或繼承Spring規(guī)范的類漓骚,相反,在基于Spring構(gòu)建的應(yīng)用中,它的類通常沒有任何痕跡表明你使用了Spring。最壞的場(chǎng)景是跪另,一個(gè)類或許會(huì)使用Spring注解,但它依舊是POJO誊垢。

Spring賦予POJO魔力的方式之一就是通過依賴注入來裝載它們乎芳。

依賴注入

任何一個(gè)有意義的應(yīng)用一般都需要多個(gè)組件帮孔,這些組件之間必定需要進(jìn)行相互協(xié)作才能完成特定的業(yè)務(wù),從而導(dǎo)致組件之間的緊耦合击喂,牽一發(fā)而動(dòng)全身
代碼示例:

package com.springinaction.knights;

public class DamselRescuingKnight implements Knight {

    private RescueDamselQuest quest;

    public DamselRescuingKnight() {
        quest = new RescueDamselQuest();// 與RescueDamselQuest緊耦合
    }

    @Override
    public void embarhOnQuest() throws QuestException {
        quest.embark();
    }

}

正如你所見工三,DamselRescuingKnight 在它的構(gòu)造函數(shù)中自行創(chuàng)建了RescueDamselQuest闹蒜,這使得DamselRescuingKnight和RescueDamselQuest緊密地耦合到了一起催式,因此極大地限制了這個(gè)騎士的執(zhí)行能力。如果一個(gè)少女需要救援奸柬,這個(gè)騎士能夠召之即來授段。但是如果一條惡龍需要?dú)⒌粞珉剩敲催@個(gè)騎士只能愛莫能助了。

另一方面拷肌,可以通過依賴注入的方式來完成對(duì)象之間的依賴關(guān)系拴清,對(duì)象不再需要自行管理它們的依賴關(guān)系木张,而是通過依賴注入自動(dòng)地注入到對(duì)象中去育拨。

代碼示例:

package com.springinaction.knights;

public class BraveKnight implements Knight {

    private Quest quest;

    public BraveKnight(Quest quest) {
        this.quest = quest;// quest被注入到對(duì)象中
    }

    @Override
    public void embarhOnQuest() throws QuestException {
        quest.embark();
    }

}

不同于之前的DamselRescuingKnight,BraveKnight沒有自行創(chuàng)建探險(xiǎn)任務(wù),而是在構(gòu)造器中把探險(xiǎn)任務(wù)作為參數(shù)注入失尖,這也是依賴注入的一種方式薯鼠,即構(gòu)造器注入暇仲。

更為重要的是,BraveKnight中注入的探險(xiǎn)類型是Quest茬贵,Quest只是一個(gè)探險(xiǎn)任務(wù)所必須實(shí)現(xiàn)的接口巷嚣。因此,BraveKnight能夠響RescueDamselQuest厨喂、SlayDraonQuest等任意一種Quest實(shí)現(xiàn)绿贞,這正是多態(tài)的體現(xiàn)耻警。

這里的要點(diǎn)是BraveKnight沒有與任何特定的Quest實(shí)現(xiàn)發(fā)生耦合荡含。對(duì)它來說误债,被要求挑戰(zhàn)的探險(xiǎn)任務(wù)只要實(shí)現(xiàn)了Quest接口箫老,那么具體是哪一類型的探險(xiǎn)就無關(guān)緊要了界斜。這就是依賴注入最大的好處--松耦合。如果一個(gè)對(duì)象只通過接口(而不是具體實(shí)現(xiàn)或初始化的過程)來表明依賴關(guān)系完残,那么這種依賴就能夠在對(duì)象本身毫不知情的情況下,用不同的具體實(shí)現(xiàn)進(jìn)行替換琴锭。

注入一個(gè)Quest到Knight

創(chuàng)建應(yīng)用組件之間協(xié)作關(guān)系的行為稱為裝配晰甚,Spring有多種裝配Bean的方式,其中最常用的就是通過XML配置文件的方式裝配决帖。
示例代碼:使用Spring將SlayDragonQuest注入到BraveKnight中厕九。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="knight" class="com.springinaction.knights.BraveKnight">
        <constructor-arg ref="quest"></constructor-arg>
    </bean>

    <bean id="quest" class="com.springinaction.knights.SlayDragonQuest"></bean>

</beans>

Spring是如何注入的?

Spring通過應(yīng)用上下文(ApplicationContext)來裝載Bean地回,ApplicationContext全權(quán)負(fù)責(zé)對(duì)象的創(chuàng)建和組裝扁远。

Spring自帶了多種ApplicationContext來加載配置,比如刻像,Spring可以使用ClassPathXmlApplicationContext來裝載XML文件中的Bean對(duì)象畅买。

package com.springinaction.knights;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("knights.xml");// 加載Spring上下文
        Knight knight = (Knight) context.getBean("knight");// 獲取knight Bean
        knight.embarhOnQuest();// 使用knight
    }
}

這個(gè)示例代碼中,Spring上下文加載了knights.xml文件细睡,隨后獲取了一個(gè)ID為knight的Bean的實(shí)例谷羞,得到該對(duì)象實(shí)例后,就可以進(jìn)行正常的使用了溜徙。需要注意的是湃缎,這個(gè)類中完全不知道是由哪個(gè)Knight來執(zhí)行何種Quest任務(wù)犀填,只有knights.xml文件知道。

應(yīng)用切面

通常情況下嗓违,系統(tǒng)由許多不同組件組成九巡,其中的每一個(gè)組件分別負(fù)責(zé)一塊特定功能。除了實(shí)現(xiàn)自身核心的功能之外蹂季,這些組件還經(jīng)常承擔(dān)著額外的職責(zé)比庄,諸如日志、事務(wù)管理和安全等乏盐,此類的系統(tǒng)服務(wù)經(jīng)常融入到有自身核心業(yè)務(wù)邏輯的組件中去佳窑,這些系統(tǒng)服務(wù)通常被稱為橫切關(guān)注點(diǎn),因?yàn)樗鼈兛偸强缭较到y(tǒng)的多個(gè)組件父能,如下圖所示神凑。

對(duì)遍布系統(tǒng)的橫切關(guān)注點(diǎn)的調(diào)用散布在各個(gè)組件里,而這些關(guān)注點(diǎn)并不是組件的核心業(yè)務(wù)
對(duì)遍布系統(tǒng)的橫切關(guān)注點(diǎn)的調(diào)用散布在各個(gè)組件里何吝,而這些關(guān)注點(diǎn)并不是組件的核心業(yè)務(wù)

AOP可以使得這些服務(wù)模塊化溉委,并以聲明的方式將它們應(yīng)用到相應(yīng)的組件中去,這樣爱榕,這些組件就具有更高內(nèi)聚性以及更加關(guān)注自身業(yè)務(wù)瓣喊,完全不需要了解可能涉及的系統(tǒng)服務(wù)的復(fù)雜性∏郑總之藻三,AOP確保POJO保持簡(jiǎn)單。

利用AOP跪者,可以將橫切關(guān)注點(diǎn)覆蓋在所需的組件之上棵帽,而這些組件不再需要額外的關(guān)注這些非核心業(yè)務(wù)。
利用AOP渣玲,可以將橫切關(guān)注點(diǎn)覆蓋在所需的組件之上逗概,而這些組件不再需要額外的關(guān)注這些非核心業(yè)務(wù)。

如圖所示忘衍,我們可以把切面想象為覆蓋在很多組件之上的一個(gè)外殼逾苫。利用AOP,你可以使用各種功能層去包裹核心業(yè)務(wù)層枚钓。這些層以聲明的方式靈活應(yīng)用到你的系統(tǒng)中铅搓,甚至你的核心應(yīng)用根本不知道它們的存在。

AOP應(yīng)用

接上面騎士的故事秘噪,現(xiàn)在需要一個(gè)詩人來歌頌騎士的勇敢事跡狸吞,代碼如下「Minstrel是中世紀(jì)的音樂記錄器」:

package com.springinaction.knights;

public class Minstrel {
    public void singBeforeQuest() { // 探險(xiǎn)之前調(diào)用
        System.out.println("Fa la la; The knight is so brave!");
    }

    public void singAfterQuest() { // 探險(xiǎn)之后調(diào)用
        System.out.println("Tee hee he; The brave knight did embark on a quest!");
    }
}

如代碼中所示,詩人會(huì)在騎士每次執(zhí)行探險(xiǎn)前和結(jié)束時(shí)被調(diào)用,完成騎士事跡的歌頌蹋偏。騎士必須調(diào)用詩人的方法完成歌頌:

package com.springinaction.knights;

public class BraveKnight implements Knight {

    private Quest quest;
    private Minstrel minstrel;

    public BraveKnight(Quest quest) {
        this.quest = quest;// quest被注入到對(duì)象中
    }
    
    public BraveKnight(Quest quest, Minstrel minstrel) {
        this.quest = quest;// quest被注入到對(duì)象中
        this.minstrel = minstrel;
    }

    @Override
    public void embarhOnQuest() throws QuestException {
        minstrel.singAfterQuest();
        quest.embark();
        minstrel.singAfterQuest();
    }

}

但是便斥,感覺是騎士在路邊抓了一個(gè)詩人為自己「歌功頌德」,而不是詩人主動(dòng)地為其傳揚(yáng)事跡威始。簡(jiǎn)單的BraveKnight類開始變得復(fù)雜枢纠,如果騎士不需要詩人,那么代碼將會(huì)更加復(fù)雜黎棠。

但是有了AOP晋渺,騎士就不再需要自己調(diào)用詩人的方法為自己服務(wù)了,這就需要把Minstrel聲明為一個(gè)切面:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="knight" class="com.springinaction.knights.BraveKnight">
        <constructor-arg ref="quest"></constructor-arg>
    </bean>

    <bean id="quest" class="com.springinaction.knights.SlayDragonQuest"></bean>

    <!-- 聲明詩人Minstrel脓斩,待切入的對(duì)象(刀) -->
    <bean id="minstrel" class="com.springinaction.knights.Minstrel"></bean>

    <aop:config>
        <aop:aspect ref="minstrel">
            <!-- 定義切面木西,即定義從哪里切入 -->
            <aop:pointcut expression="execution(* *.embarkOnQuest(..))"
                id="embark" />
            <!-- 聲明前置通知,在切入點(diǎn)之前執(zhí)行的方法 -->
            <aop:before method="singBeforeQuest" pointcut-ref="embark" />

            <!-- 聲明后置通知随静,在切入點(diǎn)之后執(zhí)行的方法  -->
            <aop:after method="singAfterQuest" pointcut-ref="embark" />
        </aop:aspect>
    </aop:config>

</beans>

通過運(yùn)行結(jié)果可以發(fā)現(xiàn)八千,在沒有改動(dòng)BraveKnight的代碼的情況下,就完成了Minstrel對(duì)其的歌頌燎猛,而且BraveKnight并不知道Minstrel的存在恋捆。

使用Spring模版

使用Spring模版可以消除很多樣板式代碼,比如JDBC重绷、JMS沸停、JNDI、REST等昭卓。

容納Bean

在Spring中愤钾,應(yīng)用對(duì)象生存于Spring容器中,如圖所示葬凳,Spring容器可以創(chuàng)建绰垂、裝載室奏、配置這些Bean火焰,并且可以管理它們的生命周期。

在Spring中胧沫,對(duì)象由Spring容器創(chuàng)建昌简、裝配、管理
在Spring中绒怨,對(duì)象由Spring容器創(chuàng)建纯赎、裝配、管理

Spring的容器實(shí)現(xiàn)

  • Bean工廠(org.springframework.beans.factory.BeanFactory):最簡(jiǎn)單的容器南蹂,提供基本的DI支持犬金;
  • 應(yīng)用上下文(org.springframework.context.ApplicationContext):基于BeanFactory之上構(gòu)建,提供面向應(yīng)用的服務(wù)。

常用的幾種應(yīng)用上下文

  • ClassPathXmlApplicationContext:從類路徑中的XML配置文件加載上下文晚顷,會(huì)在所有的類路徑(包括jar文件)下查找峰伙;
  • FileSystemXmlApplicationContext:從文件系統(tǒng)中讀取XML配置文件并加載上下文,在指定的文件系統(tǒng)路徑下查找该默;
  • XmlWebApplicationContext:讀取Web應(yīng)用下的XML配置文件并加載上下文瞳氓;

Bean的生命周期

Spring中Bean的生命周期
Spring中Bean的生命周期
  1. Spring對(duì)Bean進(jìn)行實(shí)例化;
  2. Spring將值和Bean的引用注入進(jìn)Bean對(duì)應(yīng)的屬性中栓袖;
  3. 如果Bean實(shí)現(xiàn)了BeanNameAware接口匣摘,Spring將Bean的ID傳遞給setBeanName()接口方法;
  4. 如果Bean實(shí)現(xiàn)了BeanFactoryAware接口裹刮,Spring將調(diào)setBeanFactory()接口方法音榜,將BeanFactory容器實(shí)例傳入;
  5. 如果Bean實(shí)現(xiàn)了ApplicationContextAware接口捧弃,Spring將調(diào)用setApplicationContext()接口方法囊咏,將應(yīng)用上下文的引用傳入;
  6. 如果Bean實(shí)現(xiàn)了BeanPostProcessor接口塔橡,Spring將調(diào)用postProcessBeforeInitialization()接口方法梅割;
  7. 如果Bean實(shí)現(xiàn)了InitializationBean接口,Spring將調(diào)用afterPropertiesSet()方法葛家。類似的如果Bean使用了init-method聲明了初始化方法户辞,該方法也會(huì)被調(diào)用;
  8. 如果Bean實(shí)現(xiàn)了BeanPostProcessor接口癞谒,Spring將調(diào)用ProcessAfterInitialization()方法底燎;
  9. 此時(shí)此刻,Bean已經(jīng)準(zhǔn)備就緒弹砚,可以被應(yīng)用程序使用了双仍,它們將一直駐留在應(yīng)用上下文中,直到該應(yīng)用上下文被銷毀桌吃;
  10. 如果Bean實(shí)現(xiàn)了DisposableBean接口朱沃,Spring將調(diào)用destory()方法,同樣的茅诱,如果Bean中使用了destroy-method聲明了銷毀方法逗物,也會(huì)調(diào)用該方法;

縱觀Spring

Spring模塊

Spring中的6個(gè)重要模塊
Spring中的6個(gè)重要模塊

核心Spring容器

容器是Spring框架最核心的部分瑟俭,它負(fù)責(zé)Spring應(yīng)用中Bean的創(chuàng)建翎卓、配置和管理。Spring模塊都構(gòu)建與核心容器之上摆寄,當(dāng)配置應(yīng)用時(shí)失暴,其實(shí)都隱式地使用了相關(guān)的核心容器類坯门。另外,該模塊還提供了許多企業(yè)級(jí)服務(wù)逗扒,如郵件田盈、JNDI訪問、EJB集成和調(diào)度等缴阎。

AOP

AOP是Spring應(yīng)用系統(tǒng)開發(fā)切面的基礎(chǔ)允瞧,與依賴注入一樣,可以幫助應(yīng)用對(duì)象解耦蛮拔。借助于AOP述暂,可以將遍布于應(yīng)用的關(guān)注點(diǎn)(如事務(wù)和安全等)從所應(yīng)用的對(duì)象中解耦出來。

數(shù)據(jù)訪問與集成

Spring的JDBC和DAO模塊封裝了大量的樣板代碼建炫,這樣可以使得在數(shù)據(jù)庫代碼變得簡(jiǎn)潔畦韭,也可以更專注于我們的業(yè)務(wù),還可以避免數(shù)據(jù)庫資源釋放失敗而引發(fā)的問題肛跌。另外艺配,Spring AOP為數(shù)據(jù)訪問提供了事務(wù)管理服務(wù)。同時(shí)衍慎,Spring還與流程的ORM(Object-Relational Mapping)進(jìn)行了集成转唉,如Hibernate、MyBatis等稳捆。

Web和遠(yuǎn)程調(diào)用

Spring提供了兩種Web層框架:面向傳統(tǒng)Web應(yīng)用的基于Servlet的框架和面向使用Java Portlet API的基于Portlet的應(yīng)用赠法。Spring遠(yuǎn)程調(diào)用服務(wù)集成了RMI、Hessian乔夯、Burlap砖织、JAX-WS等。

測(cè)試

Spring提供了測(cè)試模塊來測(cè)試Spring應(yīng)用末荐。


如果覺得有用侧纯,歡迎關(guān)注我的微信,有問題可以直接交流:

你的關(guān)注是對(duì)我最大的鼓勵(lì)甲脏!
你的關(guān)注是對(duì)我最大的鼓勵(lì)眶熬!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市剃幌,隨后出現(xiàn)的幾起案子聋涨,更是在濱河造成了極大的恐慌,老刑警劉巖负乡,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脊凰,居然都是意外死亡抖棘,警方通過查閱死者的電腦和手機(jī)茂腥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來切省,“玉大人最岗,你說我怎么就攤上這事〕Γ” “怎么了般渡?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長芙盘。 經(jīng)常有香客問我驯用,道長,這世上最難降的妖魔是什么儒老? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任蝴乔,我火速辦了婚禮,結(jié)果婚禮上驮樊,老公的妹妹穿的比我還像新娘薇正。我一直安慰自己,他們只是感情好囚衔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布挖腰。 她就那樣靜靜地躺著,像睡著了一般练湿。 火紅的嫁衣襯著肌膚如雪曙聂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天鞠鲜,我揣著相機(jī)與錄音宁脊,去河邊找鬼。 笑死贤姆,一個(gè)胖子當(dāng)著我的面吹牛榆苞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播霞捡,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼坐漏,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了碧信?” 一聲冷哼從身側(cè)響起赊琳,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎砰碴,沒想到半個(gè)月后躏筏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呈枉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年趁尼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埃碱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酥泞,死狀恐怖砚殿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芝囤,我是刑警寧澤似炎,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站悯姊,受9級(jí)特大地震影響羡藐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挠轴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一传睹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岸晦,春花似錦欧啤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冈在,卻和暖如春倒慧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背包券。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工纫谅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人溅固。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓付秕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侍郭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子询吴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)亮元,斷路器猛计,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 依賴注入 按照傳統(tǒng)的做法,每個(gè)對(duì)象負(fù)責(zé)管理與自己相互協(xié)作的對(duì)象的引用爆捞,這將會(huì)導(dǎo)致高度耦合和難以測(cè)試的代碼奉瘤。例如: ...
    謝隨安閱讀 535評(píng)論 0 0
  • 縱覽Spring , 讀者會(huì)發(fā)現(xiàn)Spring 可以做非常多的事情嵌削。 但歸根結(jié)底毛好, 支撐Spring的僅僅是少許的基...
    六尺帳篷閱讀 1,632評(píng)論 0 12
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評(píng)論 6 342
  • 父親的財(cái)富 微風(fēng)如裙紗一般 溫柔拂過青澀的苗圃 一雙可人的 興艷的眸子 笑意里是黃土地 給予父親的希望 童年的時(shí)候...
    零溫度閱讀 246評(píng)論 0 3