成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

20張圖剖析Spring啟動(dòng)時(shí)核心的12個(gè)步驟

開發(fā) 前端
本文主要是講一些啟動(dòng)的步驟,具體的很多技術(shù)實(shí)現(xiàn)細(xì)節(jié)、技術(shù)點(diǎn)這里就不過多贅述,如果有疑問的,可以查看三萬(wàn)字盤點(diǎn)Spring 9大核心基礎(chǔ)功能這篇文章或者公眾號(hào)菜單欄中關(guān)于Spring的文章,基本上都能找到答案。

今天來扒一扒Spring在啟動(dòng)過程中核心的12個(gè)步驟

之所以來寫這篇文章,主要是來填坑的

之前在三萬(wàn)字盤點(diǎn)Spring 9大核心基礎(chǔ)功能這篇文章的末尾中給自己挖了一個(gè)坑,提了一嘴有機(jī)會(huì)要寫這么一篇文章

但是由于Spring啟動(dòng)過程并不復(fù)雜,所以后面就沒寫了

不過,好巧不巧,剛剛好有兄弟來催更了,那么此時(shí)這個(gè)機(jī)會(huì)就來了,這篇文章也就有了

前言

Spring啟動(dòng)時(shí)候整個(gè)入口是這么一個(gè)方法

AbstractApplicationContext#refresh

總共有12個(gè)方法,也就是啟動(dòng)時(shí)的核心步驟

AbstractApplicationContext有眾多實(shí)現(xiàn),這里我選擇SpringBoot Web應(yīng)用默認(rèn)的實(shí)現(xiàn)來講

AnnotationConfigServletWebServerApplicationContext

AnnotationConfigServletWebServerApplicationContext類圖

對(duì)應(yīng)的SpringBoot版本為 2.2.5.RELEASE

高版本refresh方法會(huì)多一些日志相關(guān)的代碼,這里為了方便講解,就使用這個(gè)版本

所以后面本文提到的所有子類的方法實(shí)現(xiàn)、重寫都是指AnnotationConfigServletWebServerApplicationContext及其父類

本文主要是講一些啟動(dòng)的步驟,具體的很多技術(shù)實(shí)現(xiàn)細(xì)節(jié)、技術(shù)點(diǎn)這里就不過多贅述

如果有疑問的,可以查看三萬(wàn)字盤點(diǎn)Spring 9大核心基礎(chǔ)功能這篇文章或者公眾號(hào)菜單欄中關(guān)于Spring的文章,基本上都能找到答案

prepareRefresh

prepareRefresh整個(gè)刷新的一個(gè)步驟,這個(gè)步驟是做啟動(dòng)的一個(gè)準(zhǔn)備操作

ApplicationContext剛創(chuàng)建出來,什么也沒有,所以需要做一些準(zhǔn)備

首先是做一些狀態(tài)位的變更,表明開始啟動(dòng)了或者刷新了

后面一行

initPropertySources

initPropertySources是一個(gè)模板方法,本身是一個(gè)空實(shí)現(xiàn),是給子類用的

我們的這個(gè)子類就重寫了initPropertySources方法

圖片圖片

會(huì)將Servlet相關(guān)的配置加入到Environment中,這樣我們就能從Environment中獲取到Servlet相關(guān)的配置了

再后面一行

getEnvironment().validateRequiredProperties()

這行代碼就是校驗(yàn)一些必要的配置屬性,我們可以通過ConfigurableEnvironment來設(shè)置哪些屬性是必要的,默認(rèn)是沒有必要的

所以prepareRefresh就是做了一些前置操作,準(zhǔn)備好一些屬性配置相關(guān)的東西,后面的其它環(huán)節(jié),比如說生成Bean時(shí)可能需要用到這些配置

obtainFreshBeanFactory

這一步驟是刷新BeanFactory并且獲取BeanFactory

refreshBeanFactory() 和 getBeanFactory() 都是抽象方法,由子類來實(shí)現(xiàn)的

而子類的實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,就是給beanFactory設(shè)置一個(gè)id和返回beanFactory

beanFactory就是下面這個(gè)玩意

并且創(chuàng)建對(duì)象的ApplicationContext對(duì)象的時(shí)候就創(chuàng)建了,類型為

DefaultListableBeanFactory

所以從這就可以看出來,雖然說BeanFactory是一個(gè)接口,有非常多的實(shí)現(xiàn)

但是實(shí)際情況下,真正使用的就是DefaultListableBeanFactory

并且DefaultListableBeanFactory其實(shí)算是BeanFactory唯一真正的實(shí)現(xiàn)

除此之外,還可以得出一個(gè)結(jié)論,ApplicationContext中有一個(gè)BeanFactory(DefaultListableBeanFactory)

圖片圖片

prepareBeanFactory

上一步驟獲取到了BeanFactory,但是這個(gè)BeanFactory僅僅就是剛剛new出來的,什么也沒有

所以當(dāng)前步驟就是對(duì)BeanFactory做一些配置工作

前三行代碼

先給BeanFactory設(shè)置了一個(gè)ClassLoader,因?yàn)锽eanFactory是用來創(chuàng)建Bean,需要加載Bean class對(duì)象

然后設(shè)置了一個(gè)BeanExpressionResolver,這個(gè)是用來解析SpEL表達(dá)式的

然后添加了一個(gè)PropertyEditorRegistrar,也就是

ResourceEditorRegistrar

這個(gè)的作用就是為BeanFactory添加一堆跟資源相關(guān)的PropertyEditor

ResourceEditorRegistrar核心實(shí)現(xiàn)方法

PropertyEditor之前說過,就是進(jìn)行類型轉(zhuǎn)換的,將一個(gè)字符串轉(zhuǎn)成對(duì)應(yīng)的類型

接下來這幾行

這里主要是添加了一個(gè)BeanPostProcessor,也就是

ApplicationContextAwareProcessor

BeanPostProcessor我們都知道會(huì)在Bean的生命周期階段進(jìn)行回調(diào),是Bean的生命周期一個(gè)核心的環(huán)節(jié)

ApplicationContextAwareProcessor這個(gè)是用來處理Bean生命周期中的Aware回調(diào)有關(guān)

當(dāng)你的Bean實(shí)現(xiàn)這些接口的時(shí)候,在創(chuàng)建的時(shí)候Spring會(huì)回調(diào)這些接口,傳入對(duì)應(yīng)的對(duì)象

而后面的這行代碼

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

意思是說,如果你的Bean想注入一個(gè)EnvironmentAware對(duì)象

@Resource
private EnvironmentAware environmentAware;

這是不允許的

因?yàn)楹芎?jiǎn)單,注入一個(gè)EnvironmentAware對(duì)象,沒有實(shí)際的意義

后面的其它幾行代碼也都是這個(gè)意思

再接下來這幾行

圖片圖片

這跟上面的ignoreDependencyInterface作用相反

他是來設(shè)置依賴注入時(shí)Bean的類型所對(duì)應(yīng)的對(duì)象

比如說這行代碼

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);

這行代碼的意思就是當(dāng)你需要注入一個(gè)Bean類型為BeanFactory.class類型的時(shí)候

@Resource
private BeanFactory beanFactory;

那么實(shí)際注入的就是方法第二個(gè)參數(shù)beanFactory,也就是上面獲取的DefaultListableBeanFactory對(duì)象

同理,注入ResourceLoader、ApplicationEventPublisher、ApplicationContext時(shí),其實(shí)注入的對(duì)象都是this,也就是當(dāng)前的ApplicationContext對(duì)象

再再接下來這幾行

最開始又添加了一個(gè)BeanPostProcessor

ApplicationListenerDetector

這個(gè)BeanPostProcessor是跟ApplicationListener有關(guān)

他是將單例的ApplicationListener給添加到ApplicationContext中

再后面就是往BeanFactory里面添加一些跟配置屬性相關(guān)的單例對(duì)象,如果有哪里用到,就可以從BeanFactory中獲取到了

prepareBeanFactory就完了

正如方法名字的含義一樣,就是對(duì)BeanFactory做一些配置相關(guān)的東西

比如添加一些BeanPostProcessor,注冊(cè)一些PropertyEditor

為Bean的生成做準(zhǔn)備操作

最后畫張圖來總結(jié)一下這個(gè)方法的作用

圖片圖片

此時(shí)BeanFactory狀態(tài)就是這樣的

圖片圖片

postProcessBeanFactory

這個(gè)方法是一個(gè)模板方法

圖片圖片

本身是空實(shí)現(xiàn),是交給子類來擴(kuò)展,子類可以根據(jù)不同的特性再對(duì)BeanFactory進(jìn)行一些準(zhǔn)備工作

比如我們用的這個(gè)Web實(shí)現(xiàn)就重寫了這個(gè)方法,對(duì)BeanFactory設(shè)置一些Web相關(guān)的配置

圖片圖片

AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory

首先調(diào)用父類ServletWebServerApplicationContext的postProcessBeanFactory

圖片圖片

ServletWebServerApplicationContext#postProcessBeanFactory

前兩行代碼跟之前說的一樣,也是添加Aware接口的回調(diào)對(duì)應(yīng)的BeanPostProcessor,只不過這個(gè)Aware是跟Servlet相關(guān)的東西

接下來調(diào)用registerWebApplicationScopes方法,最終會(huì)調(diào)到下面這個(gè)方法

WebApplicationContextUtils#registerWebApplicationScopes

圖片圖片

這個(gè)方法干了兩件事

第一件事就是注冊(cè)一下Bean在Web環(huán)境下的作用域request、session,八股文中的東西

第二個(gè)就是注冊(cè)一些依賴注入時(shí)Bean類型和對(duì)應(yīng)的對(duì)象,這在日常開發(fā)中還是有用的

比如可以直接注入一個(gè)ServletRequest

@Resource
private ServletRequest servletRequest;

所以,父類的實(shí)現(xiàn)主要還是對(duì)BeanFactory進(jìn)行一些配置,只不過配置的主要是跟Web環(huán)境相關(guān)的東西

現(xiàn)在來看看AnnotationConfigServletWebServerApplicationContext自身的實(shí)現(xiàn)

圖片圖片

核心代碼就是這兩行

this.scanner.scan(this.basePackages);

this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));

scanner和reader就是下面這兩個(gè)玩意

圖片圖片

也就是說,如果這些配置都不是空的話,那么此時(shí)就會(huì)掃描對(duì)應(yīng)的包的下Bean,生成對(duì)應(yīng)的BeanDenifition,再注冊(cè)到DefaultListableBeanFactory

至于為什么會(huì)存到DefaultListableBeanFactory中,可以看看之前的文章

此時(shí)BeanFactory大概是這么一個(gè)狀態(tài)

圖片圖片

除此之外,還有一個(gè)賊重要的事

AnnotationConfigServletWebServerApplicationContext這個(gè)ApplicationContext創(chuàng)建時(shí)會(huì)去創(chuàng)建AnnotatedBeanDefinitionReader

而AnnotatedBeanDefinitionReader的構(gòu)造方法最終會(huì)調(diào)用這么一行代碼

AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)

圖片圖片

這個(gè)方法非常重要,他會(huì)去注冊(cè)一些BeanDefinition到BeanFactory中,這里我稱為Spring內(nèi)部的Bean

這里我說幾個(gè)常見和重要的

  • ConfigurationClassPostProcessor:這個(gè)是用來處理配置類的,非常重要,記住這個(gè)類,后面有大用
  • AutowiredAnnotationBeanPostProcessor:處理@Autowired、@Value注解
  • CommonAnnotationBeanPostProcessor:處理@Resource、@PostConstruct等注解

所以除了掃描出來的一些Bean對(duì)應(yīng)的BeanDefinition,還有一些Spring內(nèi)部的Bean會(huì)注冊(cè)到BeanFactory中

此時(shí)BeanFactory的狀態(tài)就如下圖所示

不過,在SpringBoot默認(rèn)情況下,不會(huì)指定包和配置類,也就不會(huì)掃描文件,生成BeanDefinition

但是內(nèi)部創(chuàng)建的BeanDefinition依然存在,并且在ApplicationContext創(chuàng)建的時(shí)候就注冊(cè)到BeanFactory中了

所以總結(jié)來說,postProcessBeanFactory這個(gè)方法是交給子類對(duì)BeanFactory做一些準(zhǔn)備操作,并且可能會(huì)掃描Bean

invokeBeanFactoryPostProcessors

從這個(gè)方法的名字可以看出,是調(diào)用BeanFactoryPostProcessor,這個(gè)步驟非常重要,而且過程有點(diǎn)繞

前置知識(shí):BeanFactoryPostProcessor及其子接口

BeanFactoryPostProcessor是一個(gè)接口,有一個(gè)方法,方法參數(shù)就是BeanFactory

通過這個(gè)方法就可以拿到BeanFactory,然后對(duì)BeanFactory做一些自己的調(diào)整

比如說,你想關(guān)閉循環(huán)依賴,你就可以實(shí)現(xiàn)這個(gè)接口,然后進(jìn)行調(diào)整

他還有一個(gè)子接口BeanDefinitionRegistryPostProcessor

這個(gè)接口是對(duì)BeanDefinitionRegistry進(jìn)行調(diào)整,BeanDefinitionRegistry就是存BeanDefinition的地方,真實(shí)的實(shí)現(xiàn)就是DefaultListableBeanFactory

所以BeanDefinitionRegistryPostProcessor的作用就是往BeanDefinitionRegistry(DefaultListableBeanFactory)中添加BeanDefinition的

再看invokeBeanFactoryPostProcessors

有了這兩個(gè)前置知識(shí)之后,我們來看看invokeBeanFactoryPostProcessors方法的實(shí)現(xiàn)

這個(gè)方法最終會(huì)調(diào)用下面方法來真正的處理

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors;

這個(gè)方法比較長(zhǎng),大致分為兩件事

  • 調(diào)用所有的BeanDefinitionRegistryPostProcessor,解析配置類,注冊(cè)BeanDefinition到DefaultListableBeanFactory中
  • 從BeanFactory中獲取所有的BeanFactoryPostProcessor進(jìn)行調(diào)用,完成對(duì)BeanFactory一些其它的擴(kuò)展

調(diào)用BeanDefinitionRegistryPostProcessor

首先第一步,先從BeanFactory中獲取到所有的BeanDefinitionRegistryPostProcessor對(duì)象,調(diào)用它的postProcessBeanDefinitionRegistry方法

還記得上一節(jié)在說注冊(cè)Spring內(nèi)部的Bean時(shí)特地強(qiáng)調(diào)的一個(gè)類ConfigurationClassPostProcessor不?

他就實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口

所以此時(shí)獲取到的就是ConfigurationClassPostProcessor

獲取ConfigurationClassPostProcessor的時(shí)候會(huì)走Bean的生命周期,也就是會(huì)回調(diào)前面添加的BeansPostProcessor,但是也沒幾個(gè)

之后會(huì)調(diào)用他的postProcessBeanDefinitionRegistry方法,來處理此時(shí)BeanFactory中的配置類

配置類從哪來,前面一直沒提到過

但是看一下ApplicationContext是如何使用的就知道了

比如說,下面這個(gè)demo

在創(chuàng)建一個(gè)ApplicationContext之后,在注冊(cè)一個(gè)Bean之后再refresh

此時(shí)這個(gè)注冊(cè)的Bean就是配置類。

如果你不注冊(cè),那是真沒有配置類,此時(shí)也就沒什么意義了。

所以,ApplicationContext一定會(huì)有一個(gè)配置類,不然沒有意義。

在SpringBoot條件下,SpringBoot在啟動(dòng)時(shí)就會(huì)將啟動(dòng)引導(dǎo)類當(dāng)做配置類給扔到BeanFactory中。

所以ConfigurationClassPostProcessor最開始處理的時(shí)候,就是處理啟動(dòng)引導(dǎo)類

我們可以在ConfigurationClassPostProcessor方法實(shí)現(xiàn)上打個(gè)斷點(diǎn)驗(yàn)證一下

在處理之前可以看見,除了幾個(gè)spring內(nèi)部的BeanDefinition之外,還有一個(gè)myApplication,就是我的啟動(dòng)引導(dǎo)類

處理的時(shí)候它會(huì)解析啟動(dòng)引導(dǎo)類的注解,進(jìn)行自動(dòng)裝配,掃描你寫的代碼的操作,之后生成BeanDefinition

當(dāng)處理完成之后我們?cè)倏纯?,DefaultListableBeanFactory有了非常多的BeanDefinition了

所以到第一步就完成了,此時(shí)BeanFactory就加載了很多Bean

圖片圖片

接下來,由于又新注冊(cè)了很多BeanDefinition,而這些里面就有可能有BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)

所以之后會(huì)重復(fù)從BeanFactory中獲取BeanDefinitionRegistryPostProcessor,調(diào)用postProcessBeanDefinitionRegistry

一直會(huì)循環(huán)下去,直到所有的BeanDefinitionRegistryPostProcessor都被調(diào)用為止

圖片圖片

由于BeanDefinitionRegistryPostProcessor繼承BeanFactoryPostProcessor

所以之后也會(huì)調(diào)用BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法

調(diào)用BeanFactoryPostProcessor

當(dāng)調(diào)完所有的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)方法

之后就會(huì)從BeanFactory獲取所有的BeanFactoryPostProcessor(除了BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)之外),調(diào)用postProcessBeanFactory方法

此時(shí)就可以通過BeanFactoryPostProcessor再次對(duì)BeanFactory進(jìn)制擴(kuò)展

總的來說,這一步驟的核心作用就是完成對(duì)BeanFactory自定義擴(kuò)展,但是由于BeanFactoryPostProcessor都是Bean,所以要第一步先加載Bean,之后才能通過BeanFactoryPostProcessor來擴(kuò)展

一張圖來總結(jié)上面主要干的事

這里簡(jiǎn)化了一些前面提到東西

registerBeanPostProcessors

上面一個(gè)步驟已經(jīng)完成了Bean的掃描和對(duì)BeanFactory的擴(kuò)展

這一節(jié)通過方法名就可以看出,是跟BeanPostProcessor相關(guān)

不過在這個(gè)方法執(zhí)行之前,我們先來看看此時(shí)BeanFactory中已經(jīng)有了哪些BeanPostProcessor

此時(shí)只有4個(gè),前3個(gè)前面都提到過,但是像我們熟知的處理@Autowired、@Resource注解的BeanPostProcessor都不在里面

所以這里就有一個(gè)非常重要的小細(xì)節(jié)

在當(dāng)前這個(gè)步驟執(zhí)行之前如果從BeanFactory中獲取Bean的話,雖然會(huì)走Bean生命周期的整個(gè)過程,但是@Autowired、@Resource注解都不會(huì)生效,因?yàn)榇藭r(shí)BeanFactory中還沒有處理這些注解的BeanPostProcessor(CommonAnnotationBeanPostProcessor等)

什么意思呢,舉個(gè)例子

比如上面一節(jié),在當(dāng)前步驟執(zhí)行之前會(huì)從BeanFactory中獲取BeanFactoryPostProcessor

假設(shè)現(xiàn)在你實(shí)現(xiàn)了BeanFactoryPostProcessor,想注入一個(gè)ApplicationContext對(duì)象

圖片圖片

此時(shí)是注入不成功的,@Resource注解不會(huì)生效,就是這個(gè)意思。

這時(shí)只能通過ApplicationContextAware方式獲取,因?yàn)橛袑?duì)應(yīng)的BeanPostProcessor(ApplicationContextAwareProcessor)

接下來我們?cè)賮砜纯磖egisterBeanPostProcessors實(shí)現(xiàn)

最終也是調(diào)用下面的方法

PostProcessorRegistrationDelegate#registerBeanPostProcessors

這個(gè)過程就沒上面那個(gè)步驟復(fù)雜了

其實(shí)就是從BeanFactory中獲取到所有的BeanPostProcessor,然后添加到BeanFactory中

不過值得注意的是,BeanPostProcessor創(chuàng)建會(huì)有優(yōu)先級(jí),優(yōu)先級(jí)高的會(huì)先被創(chuàng)建和添加到BeanFactory中

到這一步其實(shí)BeanFactory就算是準(zhǔn)備完成了,基本上跟創(chuàng)建Bean相關(guān)的前置操作幾乎都完成了

最后再來張圖總結(jié)一下這個(gè)方法干的事

initMessageSource

這個(gè)方法是處理國(guó)際化相關(guān)的操作

這個(gè)操作比較簡(jiǎn)單,就是從BeanFactory中看看有沒有Bean名稱為messageSource的Bean

有的話就使用這個(gè)MessageSource,沒有的話就用默認(rèn)的

不過SpringBoot項(xiàng)目下會(huì)自動(dòng)裝配一個(gè)MessageSource,所以此時(shí)容器中是有的

initApplicationEventMulticaster

這個(gè)方法跟上面的差不多,也是從BeanFactory找有沒有ApplicationEventMulticaster

有就用容器中的,沒有就自己創(chuàng)建一個(gè)

ApplicationEventMulticaster是真正用來發(fā)布事件的,ApplicationEventPublisher最終也是調(diào)用他來發(fā)布事件

ApplicationEventMulticaster內(nèi)部會(huì)緩存所有的監(jiān)聽器

當(dāng)通過ApplicationEventMulticaster發(fā)布事件的時(shí)候,會(huì)去找到所有的監(jiān)聽器,然后調(diào)用

onRefresh

onRefresh也是一個(gè)模板方法,本身也是空實(shí)現(xiàn)

子類重寫這個(gè)方法,會(huì)去創(chuàng)建一個(gè)Web服務(wù)器

registerListeners

這個(gè)方法其實(shí)也比較簡(jiǎn)單,就是將監(jiān)聽器給添加到ApplicationEventMulticaster中

finishBeanFactoryInitialization

這個(gè)方法首先又是老套路,就是判斷容器中有沒有ConversionService

ConversionService也是用來做類型轉(zhuǎn)換的,跟前面提到的PropertyEditor作用差不多

如果有,就把ConversionService設(shè)置到BeanFactory中

到這一步,BeanFactory才算真的準(zhǔn)備完成。。。

之后其實(shí)干的事就不太重要了

但是最后一行比較重要

beanFactory.preInstantiateSingletons();

從方法的命名就可以看出,實(shí)例化所有的單例對(duì)象

因?yàn)閷?duì)于BeanFactory的一些配置在前面都完成了,所以這里就可以來實(shí)例化所有的單例對(duì)象了

這個(gè)方法會(huì)做兩件事

第一件事就是實(shí)例化所有的非懶加載的單例Bean

實(shí)際上就是通過getBean方法來的,因?yàn)楂@取Bean,不存在的時(shí)候就會(huì)創(chuàng),會(huì)走Bean的生命周期

第二件事就是一旦單例Bean實(shí)現(xiàn)了SmartInitializingSingleton接口,就會(huì)調(diào)用SmartInitializingSingleton的afterSingletonsInstantiated方法

這個(gè)其實(shí)也算是Bean生命周期的一部分。

finishRefresh

這個(gè)方法是整個(gè)Spring容器刷新的最后一個(gè)方法

這個(gè)方法就是收尾的操作

清理一下緩存操作

之后就是初始化LifecycleProcessor

都是一樣的套路,優(yōu)先用BeanFactory中的

后面就會(huì)調(diào)用LifecycleProcessor#onRefresh方法

這個(gè)方法的作用就是,如果你的Bean實(shí)現(xiàn)了SmartLifecycle的接口,會(huì)調(diào)start的方法

隨后就發(fā)布一個(gè)ContextRefreshedEvent事件,表明容器已經(jīng)刷新完成了

在Web環(huán)境底下,這個(gè)finishRefresh方法被重寫了

主要是多干了一件事,那就是啟動(dòng)Web服務(wù)器

并且會(huì)發(fā)布了一個(gè)ServletWebServerInitializedEvent事件

這個(gè)事件在SpringBoot中用的不多

但是在SpringCloud中卻非常重要

在SpringCloud環(huán)境底下會(huì)有一個(gè)類監(jiān)聽這個(gè)事件

一旦監(jiān)聽到這個(gè)事件,SpringCloud就會(huì)將當(dāng)前的服務(wù)的信息自動(dòng)注冊(cè)到注冊(cè)中心上

這就是服務(wù)自動(dòng)注冊(cè)的原理

總結(jié)

這里再來簡(jiǎn)單回顧一下Spring啟動(dòng)大致的幾個(gè)過程

最開始的準(zhǔn)備操作,這部分就是準(zhǔn)備一些配置屬性相關(guān)的

之后連續(xù)好幾個(gè)方法都是準(zhǔn)備BeanFactory的,我把上面那張圖拿過來

整個(gè)準(zhǔn)備BeanFactory過程大致如下:

  • 先配置BeanFactory
  • 通過ConfigurationClassPostProcessor加載Bean到BeanFactory中
  • 從上一步加載的Bean中獲取BeanFactoryPostProcessor,完成對(duì)BeanFactory做自定義處理
  • 從上一步加載的Bean中獲取BeanPostProcessor,添加到BeanFactory中

當(dāng)這些步驟完成之后,BeanFactory跟Bean創(chuàng)建相關(guān)的配置幾乎算是配置完成了

之后其實(shí)就是一些ApplicationContext內(nèi)部的一些組價(jià)的初始化,比如MessageSource、ApplicationEventMulticaster等等

優(yōu)先從BeanFactory中獲取,沒有再用默認(rèn)的

到這ApplicationContext也算配置完成了,之后就可以實(shí)例化單例非懶加載的Bean了

再后面就是一些掃尾的操作,發(fā)布一個(gè)ContextRefreshedEvent事件,表明容器已經(jīng)刷新完成了

這時(shí)Spring就就算是真正啟動(dòng)完成了。

最后,如果本篇文章對(duì)你所有幫助,歡迎轉(zhuǎn)發(fā)、點(diǎn)贊、收藏、在看,非常感謝。

最后的最后,再來留個(gè)坑,有機(jī)會(huì)再來扒一扒SpringBoot在啟動(dòng)時(shí)都做了哪些事

至于啥時(shí)候填,那就等一個(gè)有緣人吧。。

責(zé)任編輯:武曉燕 來源: 三友的java日記
相關(guān)推薦

2022-10-31 07:57:18

Spring事務(wù)源碼

2023-09-28 21:37:41

HashMap多線程

2024-01-02 22:47:47

Nacos注冊(cè)中心節(jié)點(diǎn)

2020-12-04 06:37:19

HTTPS原理安全

2010-05-25 18:57:42

啟動(dòng)postfix

2019-04-22 12:25:40

UbuntuLinux IP地址

2009-02-18 16:34:32

優(yōu)化Windows啟動(dòng)時(shí)間

2021-01-20 08:34:37

HBaseNoSQL數(shù)據(jù)庫(kù)

2022-02-28 11:10:42

ZGCG1收集器

2017-12-25 13:51:32

LinuxUbuntu LinuLXD容器

2021-01-11 09:02:22

SpringJavaWeb

2021-08-26 13:55:45

systemdLinux目標(biāo)

2021-08-26 11:09:51

systemdLinux

2024-02-27 22:31:00

Feign動(dòng)態(tài)代理核心

2015-04-08 10:44:27

微軟win10

2022-11-02 13:47:20

Redis進(jìn)程內(nèi)存

2022-03-18 21:29:37

人工智能AI

2022-04-25 15:01:07

系統(tǒng)程序員調(diào)度

2010-05-06 18:42:15

Unix系統(tǒng)

2009-06-17 17:06:20

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品久久久久久婷婷天堂 | a免费视频 | 91精品国产欧美一区二区 | 欧美日韩在线视频一区 | 欧美日本在线观看 | 中文字幕中文字幕 | 精品在线一区 | 99久久婷婷国产综合精品 | 国产xxx在线观看 | 综合网在线 | 亚洲九九 | 欧美激情在线观看一区二区三区 | 日韩国产在线观看 | 精品乱码一区二区三四区视频 | 欧美日韩国产一区二区三区 | 久久久99国产精品免费 | 一区二区三区免费观看 | 四虎影院新地址 | 久久久久亚洲精品国产 | 国产成人麻豆免费观看 | 久久人爽 | 成人午夜视频在线观看 | 精品福利一区二区三区 | 亚洲成人自拍 | 午夜免费观看网站 | 99久久精品国产毛片 | 久久久久久久久久久一区二区 | 国产精品色 | 久久久久久91香蕉国产 | 男女羞羞视频在线免费观看 | 成人免费在线观看 | 久久久国产精品入口麻豆 | 国产一区二区不卡 | 亚洲成人午夜在线 | 国产精品久久久久久久久久 | 91日韩在线 | 91视频在线看 | 欧美日韩在线一区二区三区 | 久久激情网 | 狠狠操电影 | 国产网站在线免费观看 |