一环戈、SpringBootApplication背后的秘密
@springbootapplication 由三個注解 @springbootconfigtation(@Configuration)兽叮、@enableanticonfigration拗引、@componentScan三個注解組合而成涝影。
1蜡感、@Configuration
?這里的@Configuration對我們來說不陌生呻待,它就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration笛粘,SpringBoot社區(qū)推薦使用基于JavaConfig的配置形式趁怔,所以,這里的啟動類標注了@Configuration之后薪前,本身其實也是一個IoC容器的配置類润努。
@Configuration就要提到他的搭檔@Bean。使用這兩個注解就可以創(chuàng)建一個簡單的spring配置類示括,可以用來替代相應的xml配置文件铺浇。
2、@ComponentScan
@ComponentScan這個注解在Spring中很重要垛膝,它對應XML配置中的元素鳍侣,@ComponentScan的功能其實就是自動掃描并加載符合條件的組件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中繁涂。
? ? ?我們可以通過basePackages等屬性來細粒度的定制@ComponentScan自動掃描的范圍拱她,如果不指定二驰,則默認Spring框架實現(xiàn)會從聲明@ComponentScan所在類的package進行掃描
@EnableAutoConfiguration
@EnableScheduling是通過@Import將Spring調(diào)度框架相關(guān)的bean定義都加載到IoC容器扔罪。
@EnableMBeanExport是通過@Import將JMX相關(guān)的bean定義加載到IoC容器。
而@EnableAutoConfiguration也是借助@Import的幫助桶雀,將所有符合自動配置條件的bean定義加載到IoC容器矿酵,僅此而已!
@EnableAutoConfiguration會根據(jù)類路徑中的jar依賴為項目進行自動配置矗积,如:添加了spring-boot-starter-web依賴全肮,會自動添加Tomcat和Spring MVC的依賴,Spring Boot會對Tomcat和Spring MVC進行自動配置
其中棘捣,最關(guān)鍵的要屬@Import(EnableAutoConfigurationImportSelector.class)辜腺,借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都加載到當前SpringBoot創(chuàng)建并使用的IoC容器乍恐。就像一只“八爪魚”一樣评疗,借助于Spring框架原有的一個工具類:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自動配置功效才得以大功告成茵烈!
借助@Import的支持百匆,收集和注冊特定場景相關(guān)的bean定義。
SpringFactoriesLoader詳解
SpringFactoriesLoader屬于Spring框架私有的一種擴展方案呜投,其主要功能就是從指定的配置文件META-INF/spring.factories加載配置加匈。
配合@EnableAutoConfiguration使用的話存璃,它更多是提供一種配置查找的功能支持,即根據(jù)@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查找的Key雕拼,獲取對應的一組@Configuration類纵东。
@EnableAutoConfiguration自動配置的魔法騎士就變成了:從classpath中搜尋所有的META-INF/spring.factories配置文件,并將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)實例化為對應的標注了@Configuration的JavaConfig形式的IoC容器配置類悲没,然后匯總為一個并加載到IoC容器
二篮迎、深入探索SpringApplication執(zhí)行流程
1.項目啟動調(diào)用run方法,首先在這個方法里邊創(chuàng)建一個sringapplication對象實例 執(zhí)行initialize方法示姿,
在這個方法中 根據(jù)
[SpringBoot]深入淺出剖析SpringBoot的應用類型識別機制-GitShare的博客-51CTO博客
根據(jù)上文所描述的那樣 判斷該應用是否為web項目
使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationContextInitializer甜橱。
使用SpringFactoriesLoader在應用的classpath中查找并加載所有可用的ApplicationListener
推斷并設(shè)置main方法的定義類
SpringApplication實例初始化完成并且完成設(shè)置后,就開始執(zhí)行run方法的邏輯了栈戳,方法執(zhí)行伊始岂傲,首先遍歷執(zhí)行所有通過SpringFactoriesLoader可以查找到并加載的SpringApplicationRunListener。調(diào)用它們的started()方法子檀,告訴這些SpringApplicationRunListener镊掖,“嘿,SpringBoot應用要開始執(zhí)行咯褂痰!
創(chuàng)建并配置當前Spring Boot應用將要使用的Environment(包括配置要使用的PropertySource以及Profile)
遍歷調(diào)用所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應用使用的Environment準備好了咯缩歪!”。
如果SpringApplication的showBanner屬性被設(shè)置為true匪蝙,則打印banner
根據(jù)用戶是否明確設(shè)置了applicationContextClass類型以及初始化階段的推斷結(jié)果,決定該為當前SpringBoot應用創(chuàng)建什么類型的ApplicationContext并創(chuàng)建完成逛球,然后根據(jù)條件決定是否添加ShutdownHook千元,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader颤绕,當然,最重要的奥务,將之前準備好的Environment設(shè)置給創(chuàng)建好的ApplicationContext使用
ApplicationContext創(chuàng)建好之后,SpringApplication會再次借助Spring-FactoriesLoader汗洒,查找并加載classpath中所有可用的ApplicationContext-Initializer议纯,然后遍歷調(diào)用這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經(jīng)創(chuàng)建好的ApplicationContext進行進一步的處理
遍歷調(diào)用所有SpringApplicationRunListener的contextPrepared()方法。
?最核心的一步溢谤,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置加載到已經(jīng)準備完畢的ApplicationContext瞻凤。
遍歷調(diào)用所有SpringApplicationRunListener的contextLoaded()方法
調(diào)用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序阀参。
查找當前ApplicationContext中是否注冊有CommandLineRunner,如果有蛛壳,則遍歷執(zhí)行它們。
正常情況下捞挥,遍歷執(zhí)行SpringApplicationRunListener的finished()方法忧吟、(如果整個過程出現(xiàn)異常砌函,則依然調(diào)用所有SpringApplicationRunListener的finished()方法溜族,只不過這種情況下會將異常信息一并傳入處理)