springboot學(xué)習(xí)

學(xué)習(xí)整理摘自

http://www.yund.tech/zdetail.html?type=1&id=2b2a032bd98dfeb5e4113ef6624722d2



springboot啟動原理


基本啟動類

先看啟動類注解:SpringBootApplication?
@SpringBootApplication =

@Configuration(SpringBootConfiguration)+

@EnableAutoConfiguration+

@ComponentScan。

@Configuration

@Configuration及@bean兩個注解可以創(chuàng)建一個簡單的spring的配置類,用來替代xml的配置文件

xml方式定義一個bean
注解方式定義一個bean

@Configuration的注解類標(biāo)識這個類可以使用Spring IoC容器作為bean定義的來源。

@Bean注解告訴Spring,一個帶有@Bean的注解方法將返回一個對象,該對象應(yīng)該被注冊為在Spring應(yīng)用程序上下文中的bean。


@ComponentScan

功能是自動掃描符合加載條件的組件,比如(@Component)或者bean定義,最終將這些bean定義加載到ioc容器中

spring會默認(rèn)從聲明@componentScan的類的package包下開始掃面,所以springboot的啟動類最好放在根目錄下,因為默認(rèn)不指定basePackages

@EnableAutoConfiguration

借助@import的支持,收集和注冊特定場景相關(guān)的bean定義

類似EnableAutoScheduling是通過@import將spring調(diào)度框架相關(guān)的bean定義加載到ioc容器

類似EnableMBeanExport是通過@import將JMX相關(guān)的bean加載到IOC容器中

而@EnableAutoConfiguration 借助@Import(AutoConfigurationImportSelector.class)將符合自動裝配的bean加載到ioc容器中。也會根據(jù)類路徑中的jar依賴為項目自動裝配;比如spring-boot-starter-web會自動添加tomcat和springmvc進行配置

借助于Spring框架原有的一個工具類:SpringFactoriesLoader(下面詳解)的支持@EnableAutoConfiguration可以智能的自動配置功效才得以大功告成!

關(guān)鍵在于AutoConfigurationImportSelector.class
1:AutoConfigurationImportSelector? 中會調(diào)用SpringFactoriesLoader.loadFactoryNames
:2:然后會調(diào)用classloader.getresource將META-INF/spring.factories中每一個xxxAutoConfiguration文件都加載到容器中
3.讀取的配置文件如下

每個配置文件一般都有以下的條件注解:

@ConditionalOnClass : classpath中存在該類時起效

@ConditionalOnMissingClass : classpath中不存在該類時起效

@ConditionalOnBean : DI容器中存在該類型Bean時起效

@ConditionalOnMissingBean : DI容器中不存在該類型Bean時起效

@ConditionalOnSingleCandidate : DI容器中該類型Bean只有一個或@Primary的只有一個時起效

@ConditionalOnExpression : SpEL表達式結(jié)果為true時

@ConditionalOnProperty : 參數(shù)設(shè)置或者值一致時起效

@ConditionalOnResource : 指定的文件存在時起效

@ConditionalOnJndi : 指定的JNDI存在時起效

@ConditionalOnJava : 指定的Java版本存在時起效

@ConditionalOnWebApplication : Web應(yīng)用環(huán)境下起效

@ConditionalOnNotWebApplication : 非Web應(yīng)用環(huán)境下起效

SpringFactoriesLoader做法:

主要功能是從指定的配置文件中spring.factories加載配置

SpringFactoriesLoader是一個抽象類,類中定義的靜態(tài)屬性定義了其加載資源的路徑public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories",此外還有三個靜態(tài)方法:

loadFactories:加載指定的factoryClass并進行實例化。

loadFactoryNames:加載指定的factoryClass的名稱集合。

instantiateFactory:對指定的factoryClass進行實例化。


loadFactories方法

流程:先獲取類加載器,然后調(diào)用loadFactoryNames方法獲取所有的指定資源的名稱集合,接著調(diào)用instantiateFactory方法實例化這些資源類并將其添加到result集合中。

總結(jié): @EnableAutoConfiguration 自動配置就是從classpath中搜尋所有的META-INF/spring.factories配置文件,并將org.springframework.boot.autoconfigure.EnableutoConfiguration對應(yīng)的配置通過反射實例化為對應(yīng)了@Configuration的javaConfig形式的ioc容器類,然后加載到ioc容器中


講完注解接下來講run

啟動類

一.首先實例一個SpringApplication然后執(zhí)行run()

對于上下文的解釋:

上下文,上下文代表了程序當(dāng)下所運行的環(huán)境,聯(lián)系你整個app的生命周期與資源調(diào)用,是程序可以訪問到的所有資源的總和,資源可以是一個變量,也可以是一個對象的引用。-- 出自知乎

要做4件事情;

1.是否創(chuàng)建一個web類型的ApplicationContext通過deduceWebApplicationType()(主要是看dispatcherHandler和dispatcherServlet能不能被加載)

2.運用springFactoriesLoader在應(yīng)用的classpath中加載所有可用的ApplicationContextInitializer

3.同樣適用springFactoriesLoader加載classpath所有可用的ApplicationListener。將2.3步中獲取的META-INF/spring.factories中的屬性加載到springFactoriesLoader的cache中

4.推斷并設(shè)置main方法的定義類

二.run()主要做了以下的工作:

run() 主要做了以下事情

主要流程:獲取監(jiān)聽器 > 構(gòu)造應(yīng)用上下文環(huán)境 > 初始化應(yīng)用上下文 > 刷新應(yīng)用上下文前的準(zhǔn)備工作 > 刷新應(yīng)用上下文(做了ioc容器初始化過程) > 刷新后的拓展接口?

1.獲取監(jiān)聽器

進入getRunListeners

主要通過getspringFactoriesInstance方法將Application初始化時候加載的監(jiān)聽器實例化,生成運行時監(jiān)聽器EventPublishingRunListener,然后啟動監(jiān)聽器listener.starting(https://www.cnblogs.com/youzhibing/p/9603119.html? - 摘自)

2.構(gòu)造上下文環(huán)境

構(gòu)造環(huán)境方法

getOrCreateEnvironment:創(chuàng)建一個環(huán)境,判斷webapplicationType是個什么玩意,如果是webApplicationType.SERVLET 那就創(chuàng)建一個 StandardServletEnvironment

Configuration():重排,移除應(yīng)用環(huán)境中的PropertySource以及通過spring.profiles.avtive屬性,在配置文件的處理期間進行其他的配置文件的激活,分別通過configurePropertySources()及configureProfiles()

listeners.environmentPrepared() :觸發(fā)監(jiān)聽器,內(nèi)部方法與listener.starting的實現(xiàn)一致(沒有理解暫時不寫)

bindToSpringApplication(environment) :將環(huán)境信息environment綁定到SpringApplication

總結(jié):具體做了加載外部資源到environment中,包括命令行參數(shù),serveltConfigInitParams,application.yml(.properties),初始化日志系統(tǒng)


3.初始上下文

之前有一個好玩的是打印banner,可以重新修改下自己玩

printBanner


createApplicationContext

總結(jié):通過webApplicationType來獲取對應(yīng)的上下文,然后通過反射方式進行實例化(學(xué)習(xí)https://www.cnblogs.com/youzhibing/p/9686969.html)

什么是BeanDefinition: 

Spring容器里通過BeanDefinition對象來表示Bean,BeanDefinition描述了Bean的配置信息;根據(jù)BeanDefinition實例化bean,并放到bean緩存中。

spring bean配置方式:

有三種:基于XML的配置方式 、基于注解的配置方式和基于Java類的配置方式。

基于XML,這個我們都很熟,類似:<bean id="xx" class="xxx" />

基于注解,這個我們也用的比較多,入@Component、@Service、@Controller等

基于java類,spring的推薦配置方式,@Configuration配合@Bean


4.刷新應(yīng)用上下文前的準(zhǔn)備工作

prepareContext(context, environment, listeners, applicationArguments, printedBanner);

將springApplication中的部分屬性應(yīng)用到上下文,springApplication中的environment,initializers,listener應(yīng)用到spring上下文中


context.setEnvironment(environment)

將context中的environment替換成SpringApplication中創(chuàng)建的environment

postProcessApplicationContext(context);

由于當(dāng)前SpringApplication實例的屬性:beanNameGenerator和resourceLoader都為null,所以此方法目前相當(dāng)于什么也沒做。此方法可能是我們定制SpringApplication所用。

applyInitializers(context);

將SpringApplication中的initializers應(yīng)用到context中


5.刷新上下文(*挺多的)


refresh

詳細(xì)的refresh()流程:兩個重點的一個是obtainFefeshBeanFactory 另一個是?finishBeanFactoryInitialization()

(重點)obtainFefeshBeanFactory()? 這里面初始化了ioc并將bean注冊到容器中

obtainFefeshBeanFactory() >>>>refeshBeanFactory()


從指定的xml中解析beanDefinition

首先了解下ioc初始化過程:

1.ioc :?DefaultListableBeanFactory beanFactory = createBeanFactory();

1.Resource定位過程:指的是beanDefinition的資源定位,由ResourceLoader通過統(tǒng)一的Resource接口完成 > 通過getResourceByPath獲取resource的定位

2.BeanDefination的載入:把用戶定義好的bean表示成ioc容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu),這個容器內(nèi)w2部的數(shù)據(jù)結(jié)構(gòu)就是BeanDefinition > 通過loadBeanDefinitions(beanFactory)實現(xiàn)

3.向ioc容器注冊beanDefinition:通過RegisterBeanDefinitions () 中的processBeanDefinition()? 將 xml中的bean 轉(zhuǎn)成 beanDefination 并加載容器中

....


....


(重點)finishBeanFactoryInitialization() :負(fù)責(zé)初始化所有singleton bean

初始化所有剩下的單例bean


進到getbean繼續(xù)往下看doGetBean源碼


doGet


doGet


doGet


doGet


doGet

6.刷新后的拓展接口?

、

spring 三級緩存


https://blog.csdn.net/qq_44836294/article/details/107795639





為什么三級緩存


讀取spring的配置文件


zk


https://www.cnblogs.com/lsgspace/p/10508180.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容