1、因為【@SpringBootApplication】又被【@ComponentScan】注解。
2、注解【@ComponentScan】有一個屬性【useDefaultFilters】,並且默認值為【true】。
3、Spring初始化時會將啟動類加入上下文的【BeanFactory】中,然后進行后置處理器的處理。
4、后置處理器中有一個默認的配置類后置處理器。
5、在配置類后置處理器中,有一個能否加入候選配置類集合的判斷,判斷依據為該類是否被【@Configuration】注解。
6、在判定為配置類並加入候選集合后,會挨個執行方法【parse】和【doProcessConfigurationClass】進行處理。此時會通過配置類的元數據中獲取所有的【ComponentScan】注解,然后針對每個【ComponentScan】注解,通過掃描解析器【componentScanParser】進行掃描並獲取所有符合條件的【BeanDefinitionHolder】。
7、在對每個【ComponentScan】注解執行掃描解析時,會先建立一個Bean定義掃描器【ClassPathBeanDefinitionScanner】。此時就會詢問該【ComponentScan】注解的【useDefaultFilters】屬性值了。
8、當【useDefaultFilters】的屬性值為真時,該會對該掃描器注冊默認的過濾器。
9、該注冊過程的第一步就是對其【包含過濾器集合】---【includeFilters】增加對【@Component】注解的過濾。
10、在后續對每個【ClassPath】下找到的類文件進行過濾時,所有被【@Component】注解過的類就會成為候選項。所以雖然是自動完成的,但最終還是通過Spring的掃描過濾器實現的。
11、所有被掃描出的類定義中,如果還有被【@Configuration】注解過的配置類,則對其遞歸調用【parse】方法,繼續重復這個過程。
配置類中被【@Bean】注解的【method】是通過后續的【retrieveBeanMethodMetadata】方法獲取,並放入其【beanMethods】屬性中。
12、通過遍歷包路徑下的類文件得到的配置類定義是如何加入到【BeanFactory】的呢?
我們在對被【@Configuration】注解的啟動類作為候選項進行解析的時候,會先創建一個解析器,該解析器會包含對Spring上下文的信息,同時也包括實現了接口【BeanDefinitionRegistry】的【BeanFactory】的引用。
這樣在掃描完成后,通過接口【BeanDefinitionRegistry】的方法【registerBeanDefinition】將獲取到的候選【@Componet】Bean注冊到Spring上下文的【BeanFactory】中。
13、配置類中被【@Bean】注解的方法是如何加入到【BeanFactory】中Bean定義集合的呢?
前面提到過在解析候選配置類時,除了將找到的被【@Component】注解的類定義加入【BeanFactory】中外,還通過方法【retrieveBeanMethodMetadata】,將配置類中被【@Bean】注解的方法收集到配置類【ConfigurationClass】的屬性【beanMethods】中。
在解析完配置類自身后,又建立了一個Bean定義讀取器【ConfigurationClassBeanDefinitionReader】來對解析后生成的配置類進行處理,從而獲取其通過方法定義的Bean定義。
該Bean定義讀取器和類文件解析器【ConfigurationClassParser】一樣,建立時同樣擁有對Spring上下文及實現了實現了【BeanDefinitionRegistry】接口的【BeanFactory】的引用。
在處理過程中通過配置類對象的【getBeanMethods】方法,獲取被【@Bean】注解的方法,然后調用方法【loadBeanDefinitionsForBeanMethod】進行解析、構建和注冊。
在將方法轉換為Bean定義【BeanDefinition】后,然后執行接口【BeanDefinitionRegistry】的方法【registerBeanDefinition】,將其注入到【BeanFactory】的Bean定義集合中。
14、總體過程就是,Spring啟動后先根據配置文件構建上下文運行環境,然后以啟動類為起點掃描其包下的所有配置類,再掃描其它配置類,並形成【BeanDefinition】注冊到【BeanFactory】中。然后遍歷所有注冊的配置類定義,將其在掃描過程中收集到的【@Bean】方法,轉換為【BeanDefinition】並注冊到【BeanFactory】。
后續應該就是對所有的【BeanDefinition】,根據其順序、依賴關系、優先級等屬性,進行實例化並注冊到【BeanFactory】中,這部分的實現過程並沒有再深入跟蹤。