SpringApplication的run方法的實(shí)現(xiàn)是我們本次旅程的主要線路,該方法的主要流程大體可以歸納如下:
1) 如果我們使用的是SpringApplication的靜態(tài)run方法桥氏,那么次员,這個(gè)方法里面首先要?jiǎng)?chuàng)建一個(gè)SpringApplication對(duì)象實(shí)例嘀趟,然后調(diào)用這個(gè)創(chuàng)建好的SpringApplication的實(shí)例方法诫尽。在SpringApplication實(shí)例初始化的時(shí)候,它會(huì)提前做幾件事情:
根據(jù)classpath里面是否存在某個(gè)特征類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應(yīng)該創(chuàng)建一個(gè)為Web應(yīng)用使用的ApplicationContext類型矛洞。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationContextInitializer微姊。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationListener眯分。
推斷并設(shè)置main方法的定義類。
2) SpringApplication實(shí)例初始化完成并且完成設(shè)置后柒桑,就開始執(zhí)行run方法的邏輯了弊决,方法執(zhí)行伊始,首先遍歷執(zhí)行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener魁淳。調(diào)用它們的started()方法飘诗,告訴這些SpringApplicationRunListener,“嘿界逛,SpringBoot應(yīng)用要開始執(zhí)行咯昆稿!”。
3) 創(chuàng)建并配置當(dāng)前Spring Boot應(yīng)用將要使用的Environment(包括配置要使用的PropertySource以及Profile)息拜。
4) 遍歷調(diào)用所有SpringApplicationRunListener的environmentPrepared()的方法溉潭,告訴他們:“當(dāng)前SpringBoot應(yīng)用使用的Environment準(zhǔn)備好了咯!”少欺。
5) 如果SpringApplication的showBanner屬性被設(shè)置為true喳瓣,則打印banner。 【banner:英文廣告橫幅赞别,在這里面指的是運(yùn)行時(shí)輸出的SpringBoot畏陕,還可以進(jìn)行[修改]
6) 根據(jù)用戶是否明確設(shè)置了applicationContextClass類型以及初始化階段的推斷結(jié)果,決定該為當(dāng)前SpringBoot應(yīng)用創(chuàng)建什么類型的ApplicationContext并創(chuàng)建完成仿滔,然后根據(jù)條件決定是否添加ShutdownHook惠毁,決定是否使用自定義的BeanNameGenerator犹芹,決定是否使用自定義的ResourceLoader,當(dāng)然鞠绰,最重要的腰埂,將之前準(zhǔn)備好的Environment設(shè)置給創(chuàng)建好的ApplicationContext使用。 【ShutdownHook :停止服務(wù)】
7) ApplicationContext創(chuàng)建好之后蜈膨,SpringApplication會(huì)再次借助Spring-FactoriesLoader屿笼,查找并加載classpath中所有可用的ApplicationContext-Initializer,然后遍歷調(diào)用這些ApplicationContextInitializer的initialize(applicationContext)方法來對(duì)已經(jīng)創(chuàng)建好的ApplicationContext進(jìn)行進(jìn)一步的處理丈挟。
8) 遍歷調(diào)用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步志电,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經(jīng)準(zhǔn)備完畢的ApplicationContext曙咽。
10) 遍歷調(diào)用所有SpringApplicationRunListener的contextLoaded()方法。
11) 調(diào)用ApplicationContext的refresh()方法挑辆,完成IoC容器可用的最后一道工序例朱。
12) 查找當(dāng)前ApplicationContext中是否注冊(cè)有CommandLineRunner,如果有鱼蝉,則遍歷執(zhí)行它們洒嗤。
13) 正常情況下,遍歷執(zhí)行SpringApplicationRunListener的finished()方法魁亦、(如果整個(gè)過程出現(xiàn)異常渔隶,則依然調(diào)用所有SpringApplicationRunListener的finished()方法,只不過這種情況下會(huì)將異常信息一并傳入處理)
去除事件通知點(diǎn)后洁奈,整個(gè)流程如下: