Spring原理初探----IOC克握、AOP

前言

說是Java web,Spring已經(jīng)成為了事實標(biāo)準(zhǔn)线衫,Spring原理的深入學(xué)習(xí),無論是在工作中惑折,還是在面試中授账,都尤為重要。

Spring的兩個核心概念是IOC(控制反轉(zhuǎn))和AOP(面向切面編程)惨驶。想了解Spring的工作原理白热,毫無疑問,首先要從這兩個概念的Spring實現(xiàn)入手粗卜。但是Spring源碼浩如煙海屋确,里面摻雜了太多的實現(xiàn)細(xì)節(jié),入門可謂極其困難续扔。當(dāng)我正苦于難以入門時攻臀,好友介紹了tiny-spring這個開源項目,這個項目用了不到千行的代碼纱昧,就將Spring的IOC刨啸、AOP的核心流程實現(xiàn)完畢,真是居家旅行砌些、吹逼面試之必備呀呜投!

廢話少說,我們開始吧存璃!

目錄結(jié)構(gòu)

在github上clone下項目來之后仑荐,我們關(guān)注src文件夾,其余的是一些愛好者提的注釋PR纵东,恰巧被作者merge了粘招,不必理會。目錄結(jié)構(gòu)是這樣的:


目錄結(jié)構(gòu)
  1. aop包偎球,顧名思義洒扎,實現(xiàn)了Spring的AOP功能,可以通過bean的自動AOP切入衰絮,文件稍多袍冷,暫時先不展開。
  2. bean.factory包猫牡,通過BeanFactory胡诗、AbstractBeanFactoryAutowireCapableBeanFactory三個類,實現(xiàn)了BeanFactory的核心功能煌恢,詳情稍后講解骇陈。
  3. bean.io包定義了資源加載相關(guān)的抽象概念,這里的資源包括xml配置文件等瑰抵。
  4. bean.xml包中只包含一個類:XmlBeanDefinitionReader你雌,主要負(fù)責(zé)在xml配置文件中讀取bean定義。
  5. bean包其他類二汛,定義了BeanDefinition等核心概念婿崭,詳情后講。
  6. context包定義了ApplicationContext的核心概念习贫。
  7. BeanReference指的是引用類型的Bean逛球,而不是實體類。

IOC--浮沙筑臺之根基

IOC(控制翻轉(zhuǎn))是一種編程范式苫昌,可以在一定程度上解決復(fù)雜系統(tǒng)對象耦合度太高的問題,并不是Spring的專利幸海。IOC最常見的方式是DI(依賴注入)祟身,可以通過一個容器,將Bean維護(hù)起來物独,方便在其他地方直接使用袜硫,而不是重新new〉猜ǎ可以說婉陷,IOC是Spring最基本的概念,沒有IOC就沒有Spring官研。

為什么DI可以起到解耦的作用秽澳?
一個軟件系統(tǒng)包含了大量的對象,每個對象之間都有依賴關(guān)系戏羽,在普通的軟件編寫過程中担神,對象的定義分布在各個文件之中,對象之間的依賴始花,只能通過類的構(gòu)造器傳參妄讯,方法傳參的形式來完成。當(dāng)工程變大之后酷宵,復(fù)雜的邏輯會讓對象之間的依賴梳理變得異常困難亥贸。
在Spring IOC中,一般情況浇垦,我們可以在XML文件之中炕置,統(tǒng)一的編寫bean的定義,bean與bean之間的依賴關(guān)系,從而增加邏輯的清晰度讹俊。而且垦沉,bean的創(chuàng)建是由Spring來完成的,不需要編程人員關(guān)心仍劈,編程人員只需要將精力放到業(yè)務(wù)的邏輯上面厕倍,減輕了思維的負(fù)擔(dān)。

tiny-spring里面贩疙,整個beanscontext包都是用來實現(xiàn)IOC的讹弯。

beans包實現(xiàn)的核心關(guān)注點是BeanFactoryBeanFactory也叫作Bean容器这溅,顧名思義组民,是用來盛放、管理bean的悲靴。
context包實現(xiàn)的核心關(guān)注是ApplicationContext臭胜,ApplicationContext也是用來獲取Bean的,但是它更高層癞尚,它的面向用戶是Spring的使用者耸三,而BeanFactory面向的用戶更多是Spring開發(fā)者。BeanFactory定義了Bean初始化的流程浇揩,ApplicationContext定義了從XML讀取仪壮,到Bean初始化,再到使用的過程胳徽。

Bean在哪定義积锅?

剛才有說到,Spring通常通過xml文件养盗,來統(tǒng)一的描述bean缚陷,bean與bean的依賴關(guān)系。所以說爪瓜,bean的定義表述蹬跃,發(fā)生在xml配置文件之中。這個XML文件就是我們需要讀取的資源文件铆铆。

因此蝶缀,首要任務(wù)就是研究與讀取XML資源文件相關(guān)的類。

bean.io中存放的是讀取資源文件的抽象概念薄货。其中包含了三個類或者接口:

  1. Resource接口翁都,這個接口只有一個方法,InputStream getInputStream() throws IOException;谅猾。實現(xiàn)這個接口的類就是一個抽象的資源柄慰,可以獲取這個資源的輸入流鳍悠,從而獲取其中的內(nèi)容。
  2. UrlResource類坐搔,這個類實現(xiàn)了Resource接口藏研,通過構(gòu)造器傳入一個url地址,代表的是這個url所對應(yīng)的文件概行。
  3. ResourceLoader類蠢挡,只有一個方法,public Resource getResource(String location)凳忙。輸入url的文件地址(并不是真正的URL格式地址)业踏,來獲取Resource。

通過分析上面三個類涧卵、接口勤家,我們知道,這個包完成了一個任務(wù):通過ResourceLoader這個類柳恐,獲取某一個地址的Resource伐脖,從而獲取這個文件的輸入流。因為使用了Resource概念胎撤,可以使用網(wǎng)絡(luò)文件或者本地文件晓殊。

Bean如何定義?

  1. BeanDefinition是Bean定義的核心概念伤提,BeanDefinition包含了:bean的對象、bean的類類型认烁、bean的名字肿男,bean的所有屬性。這個類對bean的基本信息做好一個包裝却嗡。
  2. BeanDefinitionReader接口舶沛,只有一個方法:void loadBeanDefinitions(String location) throws Exception;,實現(xiàn)這個接口的類窗价,具有將某一個文件中的所有bean定義載入的功能如庭。所以BeanDefinitionReader定義了,在哪載入bean定義撼港,至于載入到哪里坪它、如何載入,稍后看具體實現(xiàn)帝牡。
  3. AbstractBeanDefinitionReader抽象類往毡,上面剛說了實現(xiàn)了BeanDefinitionReader接口的類,具有將某一個文件中描述的bean定義載入的功能靶溜,AbstractBeanDefinitionReader就實現(xiàn)了這樣一個抽象功能开瞭。它的作用就是定義懒震,載入到哪和如何載入的問題。在這個類里面嗤详,有兩個屬性:Map<String,BeanDefinition> registry;ResourceLoader resourceLoader;个扰。registry是一個注冊表,他保存的就是所有的Bean定義葱色,Map結(jié)構(gòu)递宅,key是bean的名字,value就是BeanDefinition冬筒。resourceLoader描述了如何載入恐锣。
  4. XmlBeanDefinitionReader這是beans.xml包里面的唯一一個方法,也是最重要的方法之一舞痰。它繼承了AbstractBeanDefinitionReader土榴,實現(xiàn)了所有方法,解決了bean定義中:在哪載入响牛、如何載入玷禽、載入到哪的三個大問題。這個類面向用戶的方法有兩個呀打,一個是loadBeanDefinitions矢赁,毫無疑問,這個是必須的贬丛。另一個是getRegistry用來獲取bean注冊表撩银,得到所有bean的信息,registry是bean們在內(nèi)存中實際的家豺憔。但是這個getRegistry方法并不是面向用戶的额获,而是面向ApplicationContext的。
  5. PropertyValuePropertyValue代表一種抽象概念恭应,在xml中抄邀,bean的屬性包括屬性名和屬性對象,PropertyValue就是這么一個實體昼榛。
  6. BeanReference代表的是Bean的屬性不是真實對象境肾,而是另一個bean的引用。

Bean的組裝全過程

上面兩部分是鋪墊胆屿,而BeanFactory才是重點對象奥喻。beans.factory包中有三個類用來定義BeanFactory相關(guān)的概念。

  1. BeanFactory接口莺掠,只有一個方法:Object getBean(String name) throws Exception;衫嵌,實現(xiàn)這個接口的類,就具有了得到一個bean的能力彻秆。
  2. AbstractBeanFactory類楔绞,較為復(fù)雜结闸。詳情后講。
  3. AutowireCapableBeanFactory繼承了AbstractBeanFactory酒朵,實現(xiàn)了applyPropertyValues方法桦锄,通過反射,將bean的所有屬性蔫耽,通過set方法注入進(jìn)去结耀。

AbstractBeanFactory有三大屬性:

  • beanDefinitionMap,類似于registry匙铡,但是他是BeanFactory里面私有的图甜,代表的是這個BeanFactory里面暫時有哪些bean定義。
  • beanDefinitionNames代表里面鳖眼,這個BeanFactory里面有哪些bean(名字)黑毅。
  • beanPostProcessors,代理處理器钦讳,AOP會用到矿瘦,詳情后講。

AbstractBeanFactory實現(xiàn)了幾大功能:

  • getBean愿卒,這是主要功能缚去,可以獲取一個Bean對象。
  • registerBeanDefinition琼开,面向ApplicationContext易结,用來將XML配置文件里面的bean定義注冊到BeanFactory里面。
  • preInstantiateSingletons柜候,面向ApplicationContext衬衬,用來在開始的時候,將所有的bean都初始化完畢改橘,避免懶加載。
  • addBeanPostProcessor添加代理處理器玉控。
  • getBeansForType飞主,在BeanFactory里面,獲取某一個類型的所有bean高诺。

經(jīng)過上面的分析碌识,我們可以知道BeanFactory完成了Bean初始化的整個流程。BeanFactory的工作流程如下:

  1. getBean, 在beanDefinitionMap里面得到bean虱而,如果沒有的話筏餐,先初始化。(為什么會沒有牡拇,因為ApplicationContext讀取xml文件時候魁瞪,只是給BeanDefinition服了類類型穆律,并沒有賦值對象,這個對象還是需要BeanFactory通過反射生成的)导俘。
  2. createBeanInstance峦耘,通過反射,根據(jù)BeanDefinition的類對象新建實體對象->將得到的bean對象賦值給beandefinition旅薄,然后將BeanDefinition里面的屬性都注入到Bean里面辅髓,這就完成了doCreateBean。
  3. initializeBean就是調(diào)用BeanPostProcessor的postProcessBeforeInitilizztion方法和postProcessAfterIntilizatin方法少梁,獲取新的bean洛口,這里會在aop中用到。

好了凯沪,到這BeanFactory就講完了第焰,下面是更重要的ApplicationContext。

ApplicationContext-用戶與BeanFactory之間的橋梁

beans.context包有三個類著洼、接口樟遣,完成了ApplicationContext的基本功能。

  1. ApplicationContext接口身笤,沒有任何方法豹悬,只是繼承了BeanFactory接口,暗示ApplicationContext與BeanFactory都是獲取Bean的地方液荸。
  2. AbstractApplicationContext抽象類瞻佛,首先,它的構(gòu)造函數(shù)接收入?yún)eanFactory娇钱,所以說ApplicationContext內(nèi)部具有一個BeanFactory伤柄。類似于一種裝飾器模式,但不是裝飾器模式文搂,類似于代理模式适刀,但也不是代理模式。fresh方法分為三個步驟:1.loadBeanDefinitions煤蹭,這個是一個模板方法笔喉,需要子類實現(xiàn),它的作用就是從某一個地方讀取BeanDefinition硝皂,然后寫入到ApplicationContext自己的BeanFactory里面常挚,這就是ApplicationContext與BeanFactory之間的聯(lián)系,也就是ApplicationContext還負(fù)責(zé)了讀取定義稽物。2. registerBeanPostProcessors奄毡,這個就是在BeanFactory里面找到BeanPostProcessor,然后將他們放到BeanFactory的beanPostProcessors容器里面贝或,方便BeanFactory初始化使用吼过。3. onRefresh初始化一遍所有的bean锐秦。
  3. ClassPathXmlApplicationContext實現(xiàn)了loadBeanDefinitions的方法,將xml文件和BeanFactory結(jié)合在一起那先。

總結(jié)-ApplicationContext初始化流程

ApplicationContext初始化流程

總結(jié)-ApplicationContext獲取bean流程

ApplicationContext getBean

AOP--移花接木之魔法

上一節(jié)农猬,講完了Spring IOC的整個流程,也就是bean從定義獲取售淡,到得到bean之間的整個流程斤葱。本節(jié),我們接觸一下Spring另一個重要概念揖闸,AOP揍堕。AOP用途十分廣泛,其中Spring內(nèi)部的聲明式事務(wù)和攔截器都是利用了AOP的強(qiáng)大威力汤纸,才得以優(yōu)雅的實現(xiàn)衩茸。
AOP是什么呢,簡單來說贮泞,它可以讓編程人員在不修改對象代碼的情況下楞慈,為這個對象添加額外的功能或者限制。
很熟悉吧啃擦,這就是代理模式囊蓝!

Java中存在兩種代理模式:
一種叫靜態(tài)代理,就是通過接口繼承復(fù)用的方式來完成的令蛉, 代理類與被代理對象實現(xiàn)相同的接口聚霜,然后代理類里面會擁有一個被代理對象,代理類與被代理對象相同的方法珠叔,活調(diào)用被代理對象的方法蝎宇,不過中間會加以限制,您翻開任何一本設(shè)計模式相關(guān)的書祷安,翻到代理模式這一節(jié)姥芥,講的就是它了。

另一種叫做動態(tài)代理汇鞭,動態(tài)代理就是允許我們在程序運(yùn)行過程中撇眯,為動態(tài)生成的對象,動態(tài)的生成代理虱咧。顯然,這比靜態(tài)代理靈活太多了锚国。
Java默認(rèn)提供了動態(tài)代理的實現(xiàn)方式腕巡,但是有限制,它要求被代理對象必須實現(xiàn)某一個接口血筑。為了突破這一限制绘沉,為普通類也可以提供代理煎楣,CGLib這個庫橫空出世。

因為AOP涉及的知識較為復(fù)雜车伞,所以我先將背景知識介紹一下择懂。

  1. Java動態(tài)代理,就是Java本身提供的代理實現(xiàn)另玖,要求對象必須實現(xiàn)某一個接口困曙。
  2. CGLib庫,為Java提供了谦去,為普通類提供代理的功能慷丽。
  3. aopalliance,aop聯(lián)盟包鳄哭,統(tǒng)一類aop編程的一些概念要糊,這個包里沒有具體的類實現(xiàn),而是定義了幾個重要的概念接口妆丘,具體的aop實現(xiàn)锄俄,要遵從這些接口編程,才能達(dá)到一定的通用性勺拣。
  4. aspectj包奶赠,實現(xiàn)了,通過一種固定的編程語言宣脉,通過這種簡單的編程語言车柠,我們可以定位到被代理的類,自動完成代理塑猖。

在aopallicance里面竹祷,定義了幾個核心概念:

  1. Advice增強(qiáng),說明這是一個羊苟,實現(xiàn)這個接口塑陵,說明這個類負(fù)責(zé)某一種形式的增強(qiáng)。
  2. Joinpoint連接點蜡励,表示切點與目標(biāo)方法連接處的信息令花。
  3. MethodInterceptor繼承了Interceptor接口,而Interceptor繼承了Advice接口凉倚,是一種Advice兼都,但是有一個方法invoke。這個方法需要一個參數(shù)MethodInvocation稽寒。
  4. MethodInvocation表示的是連接點的信息以及連接點函數(shù)的調(diào)用扮碧。
    結(jié)合上面的信息,我們發(fā)現(xiàn),其實MethodInterceptor的invoke方法慎王,調(diào)用的就是MethodInvocation的proceed方法蚓土,而這個proceed方法呢,應(yīng)該調(diào)用的肯定是Method.invoke方法赖淤。所以蜀漆,這是一種變相調(diào)用method.invoke的方式。為什么這樣做呢咱旱,猜一猜的話确丢,肯定是為了代碼的復(fù)用,哈哈哈莽龟,這是廢話蠕嫁。
    在Spring中,還定義了幾個核心概念:
  5. Pointcut毯盈,切點剃毒,可以定位類以及方法
  6. Advisor,可以獲取一個增強(qiáng)搂赋。
  7. PointcutAdvisor赘阀,定義了哪些方法,具有什么類型的增強(qiáng)脑奠。
  8. MethodMatcher表示某一個方法是否符合條件
  9. ClassFilter 定義了某個類是否符合條件基公。
  10. TargetSource被代理的對象,包括對象本身宋欺,類類型轰豆、所有接口
  11. AdvisedSupport代理相關(guān)的元數(shù)據(jù),包括被代理的對象齿诞,增強(qiáng)等酸休。
  12. ProxyFactory,代理工廠祷杈,可以獲得一個代理對象斑司,同時具有AdvisedSupport的所有特性。
  13. Cglib2AopProxy但汞,使用cglib實現(xiàn)的動態(tài)代理類宿刮,繼承了AbstractAopProxy抽象類,這個類的主要方法就是getProxy私蕾,通過什么呢僵缺,通過AdvisorSupport。
  14. ReflectiveMethodInvocation可以獲取連接點的信息踩叭,代理的對象等谤饭。
  15. JdkDynamicAopProxy,和Cglib2AopProxy類一個作用,通過AdvisorSupport來getProxy揉抵,不過是使用Java自帶的動態(tài)代理實現(xiàn)的。
    其中嗤疯,ProxyFactory是獲取一個代理對象的直接工廠冤今,而這個代理對象,可以通過Cglib2AopProxy產(chǎn)生茂缚,也可以通過JdkDynamicAopProxy產(chǎn)生戏罢。

Spring AOP之所以能夠為動態(tài)生成的Bean提供代理,得益于PostProcessor接口脚囊。我們會議IOC初始化流程中龟糕,最后一部,就是得到BeanFactory之中所有繼承了PostProcessor接口的bean悔耘,調(diào)用它們的postProcessBeforeInitilization讲岁、postProcessAfterInitilization方法,來代理bean衬以,生成新的bean缓艳。

基于這個突破口,我們只需要在xml配置文件中看峻,放入PostProcessor對象阶淘,Spring就會自動的用這寫對象,來代理真正的對象互妓。


aop目錄

在這里溪窒,我們的對象是AspectJAwareAdvisorAutoProxyCreator。
在這個對象的方法中冯勉,邏輯是這樣的澈蚌,找到xml里面所有切面bean,然后在這些bean里面珠闰,找到符合被代理類的切面bean惜浅,找到切面bean之后,就可以獲得增強(qiáng)伏嗜,切點等坛悉,于是可有構(gòu)造一個AdvisorSupport,知道了AdvisorSupport承绸,我們就能夠通過proxyFactory來獲取代理了裸影。

至于如何這個類切面是用來切入代理類的,這個就要交給PointCut來實現(xiàn)了军熏,pointcut有很多實現(xiàn)方式轩猩,這里我們用的是aspectj。具體這個類我就不細(xì)講了。

到目前位置均践,我自己已經(jīng)將整個AOP的流程搞清楚了晤锹,下面通過流程圖的形式展示出來:


AOP流程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市彤委,隨后出現(xiàn)的幾起案子鞭铆,更是在濱河造成了極大的恐慌,老刑警劉巖焦影,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件车遂,死亡現(xiàn)場離奇詭異,居然都是意外死亡斯辰,警方通過查閱死者的電腦和手機(jī)舶担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彬呻,“玉大人衣陶,你說我怎么就攤上這事》掀瘢” “怎么了祖搓?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長湖苞。 經(jīng)常有香客問我拯欧,道長,這世上最難降的妖魔是什么财骨? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任镐作,我火速辦了婚禮,結(jié)果婚禮上隆箩,老公的妹妹穿的比我還像新娘该贾。我一直安慰自己,他們只是感情好捌臊,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布杨蛋。 她就那樣靜靜地躺著,像睡著了一般理澎。 火紅的嫁衣襯著肌膚如雪逞力。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天糠爬,我揣著相機(jī)與錄音寇荧,去河邊找鬼。 笑死执隧,一個胖子當(dāng)著我的面吹牛揩抡,可吹牛的內(nèi)容都是我干的户侥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼峦嗤,長吁一口氣:“原來是場噩夢啊……” “哼蕊唐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烁设,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤刃泌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后署尤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡亚侠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年曹体,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硝烂。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡箕别,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滞谢,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布叛买,位于F島的核電站爽柒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橄教。R本人自食惡果不足惜清寇,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望护蝶。 院中可真熱鬧华烟,春花似錦、人聲如沸持灰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堤魁。三九已至喂链,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間姨涡,已是汗流浹背衩藤。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留涛漂,地道東北人赏表。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓检诗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓢剿。 傳聞我的和親對象是個殘疾皇子逢慌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)间狂,斷路器攻泼,智...
    卡卡羅2017閱讀 134,667評論 18 139
  • 本博中關(guān)于spring的文章:Spring IOC和AOP原理,Spring事務(wù)原理探究鉴象,Spring配置文件屬性...
    Maggie編程去閱讀 4,104評論 0 34
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,823評論 6 342
  • 我連忙不顧一切地抓住他的手忙菠,原來人是會死的,原來相聚的緣分不可強(qiáng)求纺弊。我疑視傅于琛牛欢,像是想從他的瞳孔鉆進(jìn)去,永生永世...
    溫柔亦有力量閱讀 589評論 0 0
  • 孩子問爸爸淆游,為什么你和媽媽不經(jīng)我同意傍睹,就把我生出來? 爸爸無言以對犹菱。 孩子的世界——腦洞大開拾稳。 可是每個成年人似乎...
    蕭筱筱閱讀 710評論 5 12