流程圖

流程解釋
組裝SpringApplication
1.resourceLoader:設(shè)置resourceload
2.設(shè)置primarySources:可以把啟動類加載進(jìn)入spring容器
3.webApplicationType:判斷當(dāng)前application應(yīng)該運行在什么環(huán)境下
4.mainApplicationClass:找出main方法啟動的class
執(zhí)行SpringApplication的run方法
獲取SpringApplicationRunListeners
1.從META-INF/spring.factories獲取SpringApplicationRunListener的集合,并依次調(diào)用的SpringApplicationRunListener的starting方法---即最終調(diào)用ApplicationListener的onApplicationEvent方法,發(fā)布springboot啟動事件
prepareEnvironment(目前profile功能已經(jīng)被maven取代了)
1.ConfigurableEnvironment:代表兩種意義:一種是profiles,用來描述哪些bean definitions是可用的;一種是properties,用來描述系統(tǒng)的配置,其來源可能是配置文件、JVM屬性文件、操作系統(tǒng)環(huán)境變量等等
2.getOrCreateEnvironment():根據(jù)webApplicationType創(chuàng)建不同的Environment
3.configureEnvironment(XX):通過configurePropertySources(environment, args)設(shè)置properties,通過configureProfiles(environment, args)設(shè)置profiles
4.listeners.environmentPrepared(environment);發(fā)布environmentPrepared事件,即調(diào)用ApplicationListener的onApplicationEvent事件
bindToSpringApplication:即把當(dāng)前的environment和當(dāng)前的springApplication綁定
6.ConfigurationPropertySources.attach(environment):將ConfigurationPropertySource放入environment的propertysource中的第一個
createApplicationContext:創(chuàng)建spring的容器
1.根據(jù)不同的webApplicationType設(shè)置不同的contextClass(容器的class類型),然后生成不同的容器實例對象
2.生成容器實例的時候,對于Kotlin類使用'primary'構(gòu)造函數(shù)實例化一個類,如果不是就使用默認(rèn)構(gòu)造函數(shù),根據(jù)得到構(gòu)造函數(shù)生成實例對象,如果構(gòu)造函數(shù)不是公共的,我們嘗試去改變并訪問
prepareContext:準(zhǔn)備容器,在準(zhǔn)備刷新容器前準(zhǔn)備好容器
1.context.setEnvironment(environment):設(shè)置spring容器的environment
2.postProcessApplicationContext(context):設(shè)置beanNameGenerator和resourceLoader
3.applyInitializers(context):調(diào)用ApplicationContextInitializer的initialize來初始化context,其中還檢測各個ApplicationContextInitializer是否接受該類型的容器
4.listeners.contextPrepared(context);即調(diào)用SpringApplicationRunListener的contextPrepared方法,但目前是個空實現(xiàn)。
5.分別注冊springApplicationArguments和springBootBanner這兩個bean
6.getAllSources就是獲取我們的primarySources和sources
7.load(context, sources.toArray(new Object[0])):首先創(chuàng)建BeanDefinitionLoader,設(shè)置該loader的sources,annotatedReader,xmlReader,scanner,以及添加scanner的ExcludeFilter(即過濾springboot的啟動類),若用戶啟動的時候設(shè)置了beanNameGenerator,resourceLoader,environment的話就替代我們自身設(shè)置的屬性。同時根據(jù)source的類型選擇不同的load方法,這邊我們是load(class),最終判斷是否是component注解,是的話就通過annotatedReader將啟動類注冊成bean
8.listeners.contextLoaded(context):首先判斷ApplicationListener是否屬于ApplicationContextAware,如果是的話就將spring容器賦值給該listener,然后將該ApplicationListener賦值給spring容器,然后調(diào)用ApplicationListener的onApplicationEvent方法
refreshContext(context):真正的刷新spring容器
一.refresh(context):
1.prepareRefresh():設(shè)置些初始的操作比如,開啟激活,啟動日期,初始化propertySource。
2.獲取beanFactory
3.prepareBeanFactory(beanFactory):設(shè)置beanFactory的classloader,BeanExpressionResolver,PropertyEditorRegistrar,ApplicationContextAwareProcessor和忽略xxxxAware,注冊依賴,還有ApplicationListenerDetector
ApplicationContextAwareProcessor:只是將applicationContext傳遞給ApplicationContextAwareProcessor,方便后面的xxxAware調(diào)用
忽略xxxxAware:忽略這些Aware接口實現(xiàn)類中與接口set方法中入?yún)㈩愋拖嗤膶傩缘牡淖詣幼⑷脒@樣就保證了關(guān)鍵的類是由spring容器自己產(chǎn)生的而不是我們注入的,
自動注入不是指的@AutoWire 而是指的是beans的default-autowire="byType" 或在bean的autowire="byType" ,這樣spring 回去ioc容器尋找類型相似的類型給其注入,如果實現(xiàn)了spring 的xxaware接口,就不會自動注入記載filterPropertyDescriptorsForDependencyCheck刪除與入?yún)㈩愋拖嗤膶傩?/p>
注冊依賴:即指定一些類自動注入的實例是spring指定的實例對象
ApplicationListenerDetector:檢測實現(xiàn)了ApplicationListener的實現(xiàn)類,因為有些實現(xiàn)類,無法通過getBeanNamesForType獲取到。
4.postProcessBeanFactory(beanFactory):繼續(xù)設(shè)置ignoreDependencyInterface(ServletContextAware)還有annotatedClasses,basePackages如果存在就設(shè)置。
5.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.registerBeanPostProcessors:從beanFactory獲取BeanPostProcessor分別按照PriorityOrdered,Ordered,普通的類型注冊BeanPostProcessor
7.BeanPostProcessor和BeanFactoryPostProcessor:前者是對bean初始化前后進(jìn)行設(shè)置,后者可以對beanFactory進(jìn)行修改 或者,可以對beanDefinition進(jìn)行修改或者增加或者初始化渴望提前初始化的bean
8.initMessageSource():一般是我們用來初始化我們國際化文件的
9.initApplicationEventMulticaster():設(shè)置applicationEventMulticaster,spring發(fā)布各種事件就依靠他,這個和springboot發(fā)布事件使用相同的類
10.onRefresh():初始化其他的子容器類中的bean,同時創(chuàng)建spring的內(nèi)置tomcat,這在后期Springboot內(nèi)嵌式tomcat中詳細(xì)闡述
11.registerListeners():添加用戶設(shè)置applicationListeners,然后從beanFactory獲取ApplicationListener,然后發(fā)布需要earlyApplicationEvents事件
12.finishBeanFactoryInitialization(beanFactory):實例化非懶加載的剩余bean
13.finishRefresh:清理資源緩存,初始化lifecycle,調(diào)用lifecycle的onrefresh,發(fā)布ContextRefreshedEvent的事件,激活JMX,啟動tomcat
二.context.registerShutdownHook():注冊一個線程,該線程主要指向doclose方法,doClose方法的邏輯就是:從applicationContexts集合中刪除當(dāng)前容器,MBeanServer卸載MBean,發(fā)布容器關(guān)閉事件,調(diào)用了實現(xiàn)了lifecycleProcessor接口的bean,destroyBeans,closeBeanFactory,onClose:關(guān)閉內(nèi)置tomcat,active設(shè)置為false
afterRefresh(context, applicationArguments):目前是空的實現(xiàn)
listeners.started(context):發(fā)布started事件
callRunners(context, applicationArguments)
1.從spring容器中獲取ApplicationRunner和CommandLineRunner對象,然后按照順序排序,循環(huán)調(diào)用他們的run方法
handleRunFailure(context, ex, exceptionReporters, listeners)
1.處理不同的異常狀態(tài),然后調(diào)用listeners.failed(context, exception),并關(guān)閉spring容器
listeners.running(context):發(fā)布running事件