溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法

發(fā)布時(shí)間:2021-09-04 11:13:35 來源:億速云 閱讀:266 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要介紹“springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法”,在日常操作中,相信很多人在springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1. 啟動(dòng)流程圖

springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法

2. 啟動(dòng)結(jié)構(gòu)圖

springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法

3.運(yùn)行流程

1. 初始化SpringApplication

  1. 設(shè)置resourceload

  2. 設(shè)置primarySources,可以把啟動(dòng)類加載進(jìn)入spring容器

  3. 判斷當(dāng)前application應(yīng)該運(yùn)行在什么環(huán)境下,即獲取webApplicationType(程序應(yīng)用類型)

  4. 加載所有classpath下面的META-INF/spring.factories中的ApplicationContextInitializer

  5. 加載所有classpath下面的META-INF/spring.factories中的ApplicationListener

  6. mainApplicationClass:找出main方法啟動(dòng)的class

2. 執(zhí)行SpringApplication的run方法

1. 設(shè)置Java.awt.headless系統(tǒng)變量

2. 獲取監(jiān)聽器SpringApplicationRunListeners

  1. 加載所有classpath下面的META-INF/spring.factories文件,獲取SpringApplicationRunListener的集合,即加載所有spring.factories文件中SpringApplicationRunListener

  2. 依次調(diào)用的SpringApplicationRunListener的starting方法,最終調(diào)用ApplicationListener的onApplicationEvent方法,發(fā)布springboot啟動(dòng)事件

3. 實(shí)例化ApplicationArguments對象獲取應(yīng)用參數(shù)

4. 創(chuàng)建并設(shè)置ConfigurableEnvironment (可配置環(huán)境)

    ConfigurableEnvironment:代表兩種意義:一種是profiles,用來描述哪些bean definitions是可用的;一種是properties,用來描述系統(tǒng)的配置,其來源可能是配置文件、JVM屬性文件、操作系統(tǒng)環(huán)境變量等等    

  1. 創(chuàng)建ConfigurableEnvironment,即執(zhí)行g(shù)etOrCreateEnvironment()方法,根據(jù)webApplicationType創(chuàng)建不同的Environment對象

  2. 配置environment,即執(zhí)行configureEnvironment(XX)方法。主要把運(yùn)行方法參數(shù)配置到environment

    1. 通過configurePropertySources(environment, args)設(shè)置properties

    2. 通過configureProfiles(environment, args)設(shè)置profiles

  3. 執(zhí)行l(wèi)isteners.environmentPrepared(environment)方法,發(fā)布environmentPrepared事件,即調(diào)用ApplicationListener的onApplicationEvent事件   

  4. 執(zhí)行bindToSpringApplication方法,即把當(dāng)前的environment和當(dāng)前的springApplication綁定

  5. 如果不是web環(huán)境,但是是web的environment,則把其轉(zhuǎn)換成標(biāo)準(zhǔn)的environment

  6. 執(zhí)行ConfigurationPropertySources.attach(environment)方法,將ConfigurationPropertySource放入environment的propertysource中的第一個(gè)

5. 打印Banner

6. 創(chuàng)建spring的容器

  1. 根據(jù)不同的webApplicationType設(shè)置不同的contextClass(容器的class類型),然后生成不同的容器實(shí)例對象

  2. 生成容器實(shí)例的時(shí)候,對于Kotlin類使用'primary'構(gòu)造函數(shù)實(shí)例化一個(gè)類,如果不是就使用默認(rèn)構(gòu)造函數(shù),根據(jù)得到構(gòu)造函數(shù)生成實(shí)例對象,如果構(gòu)造函數(shù)不是公共的,我們嘗試去改變并訪問

7. 執(zhí)行getSpringFactorInstances方法獲取具體實(shí)現(xiàn)類

8. 準(zhǔn)備容器,在準(zhǔn)備刷新容器前準(zhǔn)備好容器

  1. 執(zhí)行context.setEnvironment(environment)方法,設(shè)置spring容器的environment

  2. 執(zhí)行postProcessApplicationContext(context)方法,設(shè)置beanNameGenerator(其不未空時(shí)注入到容器中)和resourceLoader(其不未空時(shí)加載對象)

  3. 執(zhí)行applyInitializers(context),回調(diào)所有ApplicationContextInitializer的initialize來初始化context,其中還檢測各個(gè)ApplicationContextInitializer是否接受該類型的容器

  4. 執(zhí)行l(wèi)isteners.contextPrepared(context),調(diào)用SpringApplicationRunListener的contextPrepared方法,但目前是個(gè)空實(shí)現(xiàn)。

  5. 依次向容器注冊springApplicationArguments和springBootBanner這兩個(gè)bean

  6. getAllSources就是獲取我們的primarySources和sources

  7. 加載所有資源到context里,即調(diào)用load(context, sources.toArray(new Object[0]))方法創(chuàng)建BeanDefinitionLoader,設(shè)置該loader的sources,annotatedReader,xmlReader,scanner,以及添加scanner的ExcludeFilter(即過濾springboot的啟動(dòng)類),若用戶啟動(dòng)的時(shí)候設(shè)置了beanNameGenerator,resourceLoader,environment的話就替代我們自身設(shè)置的屬性。同時(shí)根據(jù)source的類型選擇不同的load方法,這邊我們是load(class),最終判斷是否是component注解,是的話就通過annotatedReader將啟動(dòng)類注冊成bean

  8. 執(zhí)行l(wèi)isteners.contextLoaded(context)方法,判斷ApplicationListener是否屬于ApplicationContextAware,如果是的話就將spring容器賦值給該listener,然后將該ApplicationListener賦值給spring容器,然后調(diào)用ApplicationListener的onApplicationEvent方法

9. 執(zhí)行refreshContext(context) 刷新spring容器

    1. refresh(context)
  1. 執(zhí)行prepareRefresh()方法設(shè)置些初始的操作。比如 開啟激活,啟動(dòng)日期,初始化propertySource。

  2. 獲取beanFactory

  3. 執(zhí)行prepareBeanFactory(beanFactory),設(shè)置beanFactory的classloader,BeanExpressionResolver,PropertyEditorRegistrar,    ApplicationContextAwareProcessor和忽略xxxxAware,注冊依賴,還有ApplicationListenerDetector

    1. 自動(dòng)注入不是指的@AutoWire 而是指的是beans的default-autowire="byType" 或在bean的autowire="byType" ,這樣spring 會(huì)去ioc容器尋找類型相似的類型給其注入,如果實(shí)現(xiàn)了spring 的xxaware接口,就不會(huì)自動(dòng)注入記載filterPropertyDescriptorsForDependencyCheck刪除與入?yún)㈩愋拖嗤膶傩?/p>

    2. ApplicationContextAwareProcessor:只是將applicationContext傳遞給ApplicationContextAwareProcessor,方便后面的xxxAware調(diào)用

    3. 忽略xxxxAware:忽略這些Aware接口實(shí)現(xiàn)類中與接口set方法中入?yún)㈩愋拖嗤膶傩缘牡淖詣?dòng)注入這樣就保證了關(guān)鍵的類是由spring容器自己產(chǎn)生的而不是我們注入的

    4. 注冊依賴:即指定一些類自動(dòng)注入的實(shí)例是spring指定的實(shí)例對象

    5. ApplicationListenerDetector:檢測實(shí)現(xiàn)了ApplicationListener的實(shí)現(xiàn)類,因?yàn)橛行?shí)現(xiàn)類,無法通過getBeanNamesForType獲取到。

  4. 執(zhí)行postProcessBeanFactory(beanFactory)方法,設(shè)置ignoreDependencyInterface(ServletContextAware)還有annotatedClasses,basePackages如果存在就設(shè)置。

  5. 執(zhí)行invokeBeanFactoryPostProcessors(beanFactory)方法,從beanFactoryPostProcessors獲取BeanFactoryPostProcessor,然后先執(zhí)行BeanDefinitionRegistryPostProcessor類型的postProcessBeanDefinitionRegistry,繼續(xù)從beanFactory獲取BeanDefinitionRegistryPostProcessor類型的bean然后執(zhí)行postProcessBeanDefinitionRegistry,執(zhí)行的過程按照PriorityOrdered,Ordered,普通的類型進(jìn)行執(zhí)行,然后優(yōu)先執(zhí)行registryProcessors的postProcessBeanFactory在執(zhí)行regularPostProcessors的postProcessBeanFactory,再從BeanFactory獲取PriorityOrdered,Ordered,普通的類型三種類型的BeanFactoryPostProcessor,并按照順序執(zhí)行??偨Y(jié):從之前加入的beanFactoryPostProcessor先執(zhí)行postProcessBeanDefinitionRegistry(假如是BeanDefinitionRegistryPostProcessor)然后在執(zhí)行postProcessBeanFactory方法,然后從beanFactory獲取BeanFactoryPostProcessor 然后執(zhí)行postProcessBeanFactory,執(zhí)行過程中都要按照PriorityOrdered,Ordered,普通的類型三種類型的順序執(zhí)行。

  6. 執(zhí)行egisterBeanPostProcessors方法,從beanFactory獲取BeanPostProcessor分別按照PriorityOrdered,Ordered,普通的類型注冊BeanPostProcessor

    1. BeanPostProcessor和BeanFactoryPostProcessor:前者是對bean初始化前后進(jìn)行設(shè)置,后者可以對beanFactory進(jìn)行修改 或者,可以對beanDefinition進(jìn)行修改或者增加或者初始化渴望提前初始化的bean

  7. 執(zhí)行initMessageSource()方法,初始化我們國際化文件

  8. 執(zhí)行initApplicationEventMulticaster()方法,設(shè)置applicationEventMulticaster,spring發(fā)布各種事件就依靠他,這個(gè)和springboot發(fā)布事件使用相同的類

  9. 執(zhí)行onRefresh()方法,初始化其他的子容器類中的bean,同時(shí)創(chuàng)建spring的內(nèi)置容器(tomcat)

  10. 執(zhí)行registerListeners()方法,添加用戶設(shè)置applicationListeners,然后從beanFactory獲取ApplicationListener,然后發(fā)布需要earlyApplicationEvents事件

  11. 執(zhí)行inishBeanFactoryInitialization(beanFactory)方法,實(shí)例化非懶加載的剩余bean

  12. 執(zhí)行finishRefresh方法,清理資源緩存,初始化lifecycle,調(diào)用lifecycle的onrefresh,發(fā)布ContextRefreshedEvent的事件,激活JMX,啟動(dòng)tomcat

  2. context.registerShutdownHook()

        注冊一個(gè)線程,該線程主要指向doclose方法,doClose方法的邏輯就是:從applicationContexts集合中刪除當(dāng)前容器,MBeanServer卸載MBean,發(fā)布容器關(guān)閉事件,調(diào)用了實(shí)現(xiàn)了lifecycleProcessor接口的bean,destroyBeans,closeBeanFactory,onClose:關(guān)閉內(nèi)置tomcat,active設(shè)置為false

10. 執(zhí)行afterRefresh(context, applicationArguments)方法(目前是空的實(shí)現(xiàn))

11. 執(zhí)行listeners.started(context)方法,發(fā)布started事件

12. 執(zhí)行callRunners(context, applicationArguments)方法

  從spring容器中獲取ApplicationRunner和CommandLineRunner對象,然后按照順序排序,循環(huán)調(diào)用他們的run方法

13. 執(zhí)行handleRunFailure(context, ex, exceptionReporters, listeners)方法

     處理不同的異常狀態(tài),然后調(diào)用listeners.failed(context, exception),并關(guān)閉spring容器

14. listeners.running(context)

    發(fā)布running事件

4. 自動(dòng)化配置

    該配置模塊的主要使用到了SpringFactoriesLoader,即Spring工廠加載器,該對象提供了loadFactoryNames方法,入?yún)閒actoryClass和classLoader,即需要傳入上圖中的工廠類名稱和對應(yīng)的類加載器,方法會(huì)根據(jù)指定的classLoader,加載該類加器搜索路徑下的指定文件,即spring.factories文件,傳入的工廠類為接口,而文件中對應(yīng)的類則是接口的實(shí)現(xiàn)類,或最終作為實(shí)現(xiàn)類,所以文件中一般為一對多的類名集合,獲取到這些實(shí)現(xiàn)類的類名后,loadFactoryNames方法返回類名集合,方法調(diào)用方得到這些集合后,再通過反射獲取這些類的類對象、構(gòu)造方法,最終生成實(shí)例

到此,關(guān)于“springboot2.0.6的運(yùn)行流程以及怎么執(zhí)行SpringApplication的run方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI