spring boot 啟動原理詳細解析 - jstarseven - 博客園
一 注入
@SpringBootApplication
中有三個重要的注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters ...)
@SpringBootConfiguration
是解決平時springboot配置的注解比如@Configuration
@ComponentScan
掃描指定包下的類將其注入
@EnableAutoConfiguration
這個厲害是將依賴的所有jar中帶@注解的注入。
二 啟動流程
1) 如果我們使用的是SpringApplication的靜態(tài)run方法允耿,那么坠韩,這個方法里面首先要創(chuàng)建一個SpringApplication對象實例,然后調(diào)用這個創(chuàng)建好的SpringApplication的實例方法甜熔。在SpringApplication實例初始化的時候,它會提前做幾件事情:
根據(jù)classpath里面是否存在某個特征類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應(yīng)該創(chuàng)建一個為Web應(yīng)用使用的ApplicationContext類型突倍。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationContextInitializer腔稀。
使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的ApplicationListener。
推斷并設(shè)置main方法的定義類羽历。
2) SpringApplication實例初始化完成并且完成設(shè)置后焊虏,就開始執(zhí)行run方法的邏輯了,方法執(zhí)行伊始秕磷,首先遍歷執(zhí)行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener诵闭。調(diào)用它們的started()方法,告訴這些SpringApplicationRunListener澎嚣,“嘿疏尿,SpringBoot應(yīng)用要開始執(zhí)行咯!”易桃。
3) 創(chuàng)建并配置當前Spring Boot應(yīng)用將要使用的Environment(包括配置要使用的PropertySource以及Profile)褥琐。
4) 遍歷調(diào)用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應(yīng)用使用的Environment準備好了咯晤郑!”敌呈。
5) 如果SpringApplication的showBanner屬性被設(shè)置為true贸宏,則打印banner。
6) 根據(jù)用戶是否明確設(shè)置了applicationContextClass類型以及初始化階段的推斷結(jié)果磕洪,決定該為當前SpringBoot應(yīng)用創(chuàng)建什么類型的ApplicationContext并創(chuàng)建完成吭练,然后根據(jù)條件決定是否添加ShutdownHook,決定是否使用自定義的BeanNameGenerator褐鸥,決定是否使用自定義的ResourceLoader线脚,當然,最重要的叫榕,將之前準備好的Environment設(shè)置給創(chuàng)建好的ApplicationContext使用浑侥。
7) ApplicationContext創(chuàng)建好之后,SpringApplication會再次借助Spring-FactoriesLoader晰绎,查找并加載classpath中所有可用的ApplicationContext-Initializer寓落,然后遍歷調(diào)用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經(jīng)創(chuàng)建好的ApplicationContext進行進一步的處理。
8) 遍歷調(diào)用所有SpringApplicationRunListener的contextPrepared()方法荞下。
9)?最核心的一步伶选,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經(jīng)準備完畢的ApplicationContext。
10) 遍歷調(diào)用所有SpringApplicationRunListener的contextLoaded()方法尖昏。
11) 調(diào)用ApplicationContext的refresh()方法仰税,完成IoC容器可用的最后一道工序。
12) 查找當前ApplicationContext中是否注冊有CommandLineRunner抽诉,如果有陨簇,則遍歷執(zhí)行它們。
13) 正常情況下迹淌,遍歷執(zhí)行SpringApplicationRunListener的finished()方法河绽、(如果整個過程出現(xiàn)異常,則依然調(diào)用所有SpringApplicationRunListener的finished()方法唉窃,只不過這種情況下會將異常信息一并傳入處理)