你來說一下springboot的啟動時的一個自動裝配過程吧
Can be present in multiple JAR files. */ public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; ``` 所以第一個端核心程式碼的意思是: 啟動的時候會掃描所有jar包下`META-INF/spring.factories`這個檔案。第二段程式碼的意思是將這些掃描到的檔案轉成Properties物件,後面兩個核心程式碼的意思就是說將載入到的Properties物件放入到快取中。 然後`getCandidateConfigurations()`方法,是隻獲取了key是`EnableAutoConfiguration.class`的配置。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020121322235276.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,,size_16,color_FFFFFF,t_70) 我們看到`getCandidateConfigurations()`方法,通過S`pringFactoriesLoader.loadFactoryNames()`獲取到了118個配置。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201213223115595.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,,size_16,color_FFFFFF,t_70) 那麼我們來看一個`spring.factories`檔案中的內容是什麼樣子的呢? ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020121322393196.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,,size_16,color_FFFFFF,t_70) 原來是這種形式的,看來這和上一篇文章中講解的Java中的SPI機制載入介面實現很像啊,其實通過查閱資料發現,這就是一種自定義SPI的實現方式的功能。 那麼我們以第一個配置類: `org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration`來看一下,這些類都是如果實現的。 開啟`org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration`的原始碼: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201213224336537.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_SmlNb2Vy,size_16,color_FFFFFF,t_70) 我們看到這個類有三個註解`@Configuration`、`@AutoConfigureAfter`、`@ConditionalOnProperty`、因為有`@Configuration`註解所以它也是一個配置類,然後第二註解中的引數類`JmxAutoConfiguration.class`進入之後是這樣的: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201213224743889.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTY1MDAw,size_16,color_FFFFFF,t_70) 也是存在`@ConditionalOnProperty`註解的。那看來關鍵點就是`@ConditionalOnProperty`這個註解了。 這個註解其實是一個條件判斷註解,這個條件註解後面的引數的意思是當存在系統屬性字首為`spring.application.admin`,並且屬性名稱為`enabled`,並且值為`true`時,才載入當前這個Bean並進行例項化。 這種spring4.0後面出現的的條件註解,可以極大的增加了框架的靈活性和擴充套件性,可以保證很多元件可以通過後期配置,而且閱讀原始碼的人,通過這些註解就能明白在什麼情況下才會例項化當前Bean。 後面還有不少這種條件註解呢: >@ConditionalOnBean:當容器裡有指定Bean的條件下 @ConditionalOnClass:當類路徑下有指定的類的條件下 @ConditionalOnExpression:基於SpEL表示式為true的時候作為判斷條件才去例項化 @ConditionalOnJava:基於JVM版本作為判斷條件 @ConditionalOnJndi:在JNDI存在的條件下查詢指定的位置 @ConditionalOnMissingBean:當容器裡沒有指定Bean的情況下 @ConditionalOnMissingClass:當容器裡沒有指定類的情況下 @ConditionalOnWebApplication:當前專案時Web專案的條件下 @ConditionalOnNotWebApplication:當前專案不是Web專案的條件下 @ConditionalOnProperty:指定的屬性是否有指定的值 @ConditionalOnResource:類路徑是否有指定的值 @ConditionalOnOnSingleCandidate:當指定Bean在容器中只有一個,或者有多個但是指定首選的Bean 這些註解其實都是通過@Conditional註解擴充套件而來的,只是使用了不同的組合條件來判斷是否需要載入和初始化當前Bean。 ## 總結 好了,最後總結一下,當面試官問springboot的自動裝配原理的時候,不能這麼長篇大論的說吧,畢竟這麼多內容也記不住啊。 所以總結: ==springboot啟動時,是依靠啟動類的main方法來進行啟動的,而main方法中執行的是`SpringApplication.run()`方法,而`SpringApplication.run()`方法中會建立spring的容器,並且重新整理容器。而在重新整理容器的時候就會去解析啟動類,然後就會去解析啟動類上的`@SpringBootApplication`註解,而這個註解是個複合註解,這個註解中有一個`@EnableAutoConfiguration`註解,這個註解就是開啟自動配置,這個註解中又有`@Import`註解引入了一個`AutoConfigurationImportSelector`這個類,這個類會進過一些核心方法,然後去掃描我們所有jar包下的`META-INF`下的`spring.factories`檔案,而從這個配置檔案中取找key為`EnableAutoConfiguration`類的全路徑的值下面的所有配置都載入,這些配置裡面都是有條件註解的,然後這些條件註解會根據你當前的專案依賴的jar包以及是否配置了符合這些條件註解的配置來進行裝載的。== 這就是springboot自動配置的過程。 #### 其實上面這些內容還是有點多,而且還有好多註解的單詞也不好記,那換成大白話,再精煉一下: **SpringBoot在啟動的時候會呼叫run()方法,run()方法會重新整理容器,重新整理容器的時候,會掃描classpath下面的的包中META-INF/spring.factories檔案,在這個檔案中記錄了好多的自動配置類,在重新整理容器的時候會將這些自動配置類載入到容器中,然後在根據這些配置類中的條件註解,來判斷是否將這些配置類在容器中進行例項化,這些條件主要是判斷專案是否有相關jar包或是否引入了相關的bean。這樣springboot就幫助我們完成了自動裝