SpringBoot 啟動類 @SpringBootApplication 註解 以及執行流程
@SpringBootApplication : 是Sprnig Boot專案的核心註解,目的是開啟自動配置
目錄
spingboot建議的目錄結果如下:
root package結構:com.example.myproject
(一)、@ComponentScan 註解
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
1、@ComponentScan這個註解在Spring中很重要,它對應XML配置中的元素,@ComponentScan的功能其實就是自動掃描並載入符合條件的元件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義載入到IoC容器中。
我們可以通過basePackages等屬性來細粒度的定製@ComponentScan自動掃描的範圍,如果不指定,則預設Spring框架實現會從宣告@ComponentScan所在類的package進行掃描。
注:所以SpringBoot的啟動類最好是放在root package下,因為預設不指定basePackages。
2、@ComponentScan告訴Spring 哪個packages 的用註解標識的類 會被spring自動掃描並且裝入bean容器。
例如,如果你有個類用@Controller註解標識了,那麼,如果不加上@ComponentScan,自動掃描該controller,那麼該Controller就不會被spring掃描到,更不會裝入spring容器中,因此你配置的這個Controller也沒有意義。
3、引數的作用
basePackageClasses:對basepackages()指定掃描註釋元件包型別安全的替代。 excludeFilters:指定不適合元件掃描的型別。 includeFilters:指定哪些型別有資格用於元件掃描。 lazyInit:指定是否應註冊掃描的beans為lazy初始化。 nameGenerator:用於在Spring容器中的檢測到的元件命名。 resourcePattern:控制可用於元件檢測的類檔案。 scopedProxy:指出代理是否應該對檢測元件產生,在使用過程中會在代理風格時尚的範圍是必要的。 scopeResolver:用於解決檢測到的元件的範圍。 useDefaultFilters:指示是否自動檢測類的註釋
(二)、@EnableAutoConfiguration 註解
@EnableAutoConfiguration 簡單概括一下就是,藉助@Import的支援,收集和註冊特定場景相關的bean定義。
- @EnableScheduling是通過@Import將Spring排程框架相關的bean定義都載入到IoC容器。
- @EnableMBeanExport是通過@Import將JMX相關的bean定義載入到IoC容器。
而@EnableAutoConfiguration也是藉助@Import的幫助,將所有符合自動配置條件的bean定義載入到IoC容器,僅此而已!
@EnableAutoConfiguration作為一個複合Annotation,其自身定義關鍵資訊如下:
其中,最關鍵的要屬@Import(AutoConfigurationImportSelector.class),藉助AutoConfigurationImportSelector,@EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都載入到當前SpringBoot建立並使用的IoC容器。
自動配置幕後英雄:SpringFactoriesLoader詳解
SpringFactoriesLoader屬於Spring框架私有的一種擴充套件方案,其主要功能就是從指定的配置檔案META-INF/spring.factories載入配置。
配合@EnableAutoConfiguration使用的話,它更多是提供一種配置查詢的功能支援,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查詢的Key,獲取對應的一組@Configuration類
上圖就是從SpringBoot的autoconfigure依賴包中的META-INF/spring.factories配置檔案中摘錄的一段內容,可以很好地說明問題。
所以,@EnableAutoConfiguration自動配置的魔法騎士就變成了:從classpath中搜尋所有的META-INF/spring.factories配置檔案,並將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)例項化為對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,然後彙總為一個並載入到IoC容器。
(三)、@SpringBootConfiguration 註解
@SpringBootConfiguration繼承自@Configuration,二者功能也一致,標註當前類是配置類,
並會將當前類內宣告的一個或多個以@Bean註解標記的方法的例項納入到spring容器中,並且例項名就是方法名。
(四)、@Inherited 註解
關於java中元註解Inherited 的使用說明
首先解釋下元註解,就是用來中宣告註解型別時需要使用到的註解。
Inherited作用是,使用此註解宣告出來的自定義註解,在使用此自定義註解時,如果註解在類上面時,子類會自動繼承此註解,否則的話,子類不會繼承此註解。這裡一定要記住,使用Inherited宣告出來的註解,只有在類上使用時才會有效,對方法,屬性等其他無效。
宣告的此註解使用了Inherited元註解,表示此註解用在類上時,會被子類所繼承
(五)、@Documented 註解
Documented註解表明這個註釋是由 javadoc記錄的,在預設情況下也有類似的記錄工具。 如果一個型別宣告被註釋了文件化,它的註釋成為公共API的一部分。
(六)、@Retention() 註解
RetentionPolicy這個列舉型別的常量描述保留註釋的各種策略,它們與元註釋(@Retention)一起指定註釋要保留多長時間
(七)、@Target() 註解
ElementType 這個列舉型別的常量提供了一個簡單的分類:註釋可能出現在Java程式中的語法位置(這些常量與元註釋型別(@Target)一起指定在何處寫入註釋的合法位置)
===========================================================================================
===========================================================================================
深入探索SpringApplication執行流程
SpringApplication的run方法的實現是我們本次旅程的主要線路,該方法的主要流程大體可以歸納如下:
1) 如果我們使用的是SpringApplication的靜態run方法,那麼,這個方法裡面首先要建立一個SpringApplication物件例項,然後呼叫這個建立好的SpringApplication的例項方法。在SpringApplication例項初始化的時候,它會提前做幾件事情:
-
根據classpath裡面是否存在某個特徵類(org.springframework.web.context.ConfigurableWebApplicationContext)來決定是否應該建立一個為Web應用使用的ApplicationContext型別。
-
使用SpringFactoriesLoader在應用的classpath中查詢並載入所有可用的ApplicationContextInitializer。
-
使用SpringFactoriesLoader在應用的classpath中查詢並載入所有可用的ApplicationListener。
-
推斷並設定main方法的定義類。
2) SpringApplication例項初始化完成並且完成設定後,就開始執行run方法的邏輯了,方法執行伊始,首先遍歷執行所有通過SpringFactoriesLoader可以查詢到並載入的SpringApplicationRunListener。呼叫它們的started()方法,告訴這些SpringApplicationRunListener,“嘿,SpringBoot應用要開始執行咯!”。
3) 建立並配置當前Spring Boot應用將要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍歷呼叫所有SpringApplicationRunListener的environmentPrepared()的方法,告訴他們:“當前SpringBoot應用使用的Environment準備好了咯!”。
5) 如果SpringApplication的showBanner屬性被設定為true,則列印banner。 【banner:英文廣告橫幅,在這裡面指的是執行時輸出的SpringBoot,還可以進行修改】
6) 根據使用者是否明確設定了applicationContextClass型別以及初始化階段的推斷結果,決定該為當前SpringBoot應用建立什麼型別的ApplicationContext並建立完成,然後根據條件決定是否新增ShutdownHook,決定是否使用自定義的BeanNameGenerator,決定是否使用自定義的ResourceLoader,當然,最重要的,將之前準備好的Environment設定給建立好的ApplicationContext使用。 【ShutdownHook :停止服務】
7) ApplicationContext建立好之後,SpringApplication會再次藉助Spring-FactoriesLoader,查詢並載入classpath中所有可用的ApplicationContext-Initializer,然後遍歷呼叫這些ApplicationContextInitializer的initialize(applicationContext)方法來對已經建立好的ApplicationContext進行進一步的處理。
9) 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置載入到已經準備完畢的ApplicationContext。
10) 遍歷呼叫所有SpringApplicationRunListener的contextLoaded()方法。
11) 呼叫ApplicationContext的refresh()方法,完成IoC容器可用的最後一道工序。
12) 查詢當前ApplicationContext中是否註冊有CommandLineRunner,如果有,則遍歷執行它們。
13) 正常情況下,遍歷執行SpringApplicationRunListener的finished()方法、(如果整個過程出現異常,則依然呼叫所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常資訊一併傳入處理)
去除事件通知點後,整個流程如下:
參考: