1. 程式人生 > >@SpringBootApplication : 是Sprnig Boot專案的核心註解,目的是開啟自動配置

@SpringBootApplication : 是Sprnig Boot專案的核心註解,目的是開啟自動配置

@SpringBootApplication  : 是Sprnig Boot專案的核心註解,目的是開啟自動配置

 

目錄

@SpringBootApplication  : 是Sprnig Boot專案的核心註解,目的是開啟自動配置

(一)、@ComponentScan 註解

(二)、@EnableAutoConfiguration 註解

(三)、@SpringBootConfiguration 註解

(四)、@Inherited 註解

宣告的此註解使用了Inherited元註解,表示此註解用在類上時,會被子類所繼承

(五)、@Documented 註解

(六)、@Retention() 註解

(七)、@Target()  註解

                     深入探索SpringApplication執行流程

 

spingboot建議的目錄結果如下:

root package結構:com.example.myproject


大家可以先認識一下@interface  : java 中@interface 和interface 的區別

(一)、@ComponentScan 註解


  
  1. @ ComponentScan( excludeFilters = {
  2. @ Filter( type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  3. @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、引數的作用


  
  1. basePackageClasses:對basepackages()指定掃描註釋元件包型別安全的替代。
  2. excludeFilters:指定不適合元件掃描的型別。
  3. includeFilters:指定哪些型別有資格用於元件掃描。
  4. lazyInit:指定是否應註冊掃描的beans為 lazy初始化。
  5. nameGenerator:用於在 Spring容器中的檢測到的元件命名。
  6. resourcePattern:控制可用於元件檢測的類檔案。
  7. scopedProxy:指出代理是否應該對檢測元件產生,在使用過程中會在代理風格時尚的範圍是必要的。
  8. scopeResolver:用於解決檢測到的元件的範圍。
  9. 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 註解


  
  1. @SpringBootConfiguration繼承自 @Configuration,二者功能也一致,標註當前類是配置類,
  2. 並會將當前類內宣告的一個或多個以 @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進行進一步的處理。

8) 遍歷呼叫所有SpringApplicationRunListener的contextPrepared()方法。

9) 最核心的一步,將之前通過@EnableAutoConfiguration獲取的所有配置以及其他形式的IoC容器配置載入到已經準備完畢的ApplicationContext。

10) 遍歷呼叫所有SpringApplicationRunListener的contextLoaded()方法。

11) 呼叫ApplicationContext的refresh()方法,完成IoC容器可用的最後一道工序。

12) 查詢當前ApplicationContext中是否註冊有CommandLineRunner,如果有,則遍歷執行它們。

13) 正常情況下,遍歷執行SpringApplicationRunListener的finished()方法、(如果整個過程出現異常,則依然呼叫所有SpringApplicationRunListener的finished()方法,只不過這種情況下會將異常資訊一併傳入處理)

去除事件通知點後,整個流程如下:

                 

                           

 

參考:

1、Spring Boot乾貨系列:(三)啟動原理解析

2、@componentscan註解的用法和作用 

3、excludeFilters:  

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html#excludeFilters--

4、@SpringBootConfiguration註解

5、關於java 註解中元註解Inherited的使用詳解

6、Java註解之 @Target、@Retention、@Documented簡介