javascript
SpringBoot(2.4.0)自动配置原理(源码)
一、從@SpringBootApplication講起
出現3個重要注解:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
二、@SpringBootConfiguration(標注當前類是配置類)
為什么@SpringBootApplication注解里沒有包含@Configuration,實際上是在@SpringBootConfiguration里面。
@SpringBootConfiguration繼承自@Configuration,二者功能也一致,標注當前類是配置類,
并會將當前類內聲明的一個或多個以@Bean注解標記的方法的實例納入到spring容器中,并且實例名就是方法名。實際上如果我們使用如下的Springboot啟動類,整個SpringBoot應用依然可以與之前的啟動類功能對等。
三、@EnableAutoConfiguration(根據類路徑下的jar包依賴為當前項目進行自動配置)
比如@EnableScheduling,@EnableCaching,@EnableMBeanExport等@EnableAutoConfiguration的理念和"做事方式"其實一脈相承,借助@Import的支持,收集和注冊特定場景相關的bean定義:
- @EnableScheduling是通過@Import將Spring調度框架相關的bean定義都加載到Ioc容器中。
- @EnableMBeanExport是通過@Import將JMX相關的bean定義加載到Ioc容器
- @EnableAutoConfiguration也是借助@Import的幫助,將所有符合自動配置條件的bean定義加載到Ioc容器,僅此而已
@AutoConfigurationPackage,@Import({AutoConfigurationImportSelector.class})又得好好研究
- 它指定了默認的包規則
- 源碼:
那就要看看Registrar這個類了:
里面這段代碼,就是批量注冊:
- AutoConfigurationImportSelector.class有一個 selectImports方法
可以看到,核心就是getAutoConfigurationEntry方法,進去看一下:
我們又發現,configurations的獲得是依賴getCandidateConfigurations方法的,進去看看,就可以看到自動配置的幕后英雄:SpringFactoriesLoader
自動配置的幕后英雄:SpringFactoriesLoader
SpringFactoriesLoader的主要功能就是從指定的配置文件META/spring.factories加載配置,spring.factories是一個典型的java properties文件,配置格式為Key-Value形式,只不過Key和Value都是Java類型的完整類名。
進入loadFactoryNames()方法,就發現loadFactoryNames()讀取了ClassPath下面的 META-INF/spring.factories 文件。
@EnableAutoConfiguration的場景中,它更多是提供一種配置查找的功能支持,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查找的key,獲取對應的一組@Configuration類
- 總結:
- 1、利用getAutoConfigurationEntry(annotationMetadata);給容器中批量導入一些組件
- 2、調用List configurations = getCandidateConfigurations(annotationMetadata, attributes)獲取到所有需要導入到容器中的配置類
- 3、利用工廠加載 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的組件
- 4、從META-INF/spring.factories位置來加載一個文件。默認掃描我們當前系統里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.4.0.RELEASE.jar包里面也有META-INF/spring.factories
-
在spring-boot-autoconfigure-2.4.0.RELEASE.jar包里的META-INF/spring.factories文件,寫死了spring-boot一啟動就要給容器中加載的所有配置類,但是你我肯定都知道,不會一下子加載那么多,那么就是另一個內容了:按需加載
-
開啟按需加載
SpringBoot自動配置是需要滿足相應的條件才會自動配置,因此SpringBoot的自動配置大量應用了條件注解ConditionalOnXXX。如下圖:
上面這些注解會被使用在各個組件上面,然后會根據環境決定是否導入各個組件,實現按需導入,源碼分析
四、@ComponentScan (自動掃描并加載符合條件的組件或者bean定義)
@ComponentScan的功能其實就是自動掃描并加載符合條件的組件或bean定義,最終將這些bean定義加載到容器中。我們可以通過basePackages等屬性指定@ComponentScan自動掃描的范圍,如果不指定,則默認Spring框架實現從聲明@ComponentScan所在類的package進行掃描,默認情況下是不指定的,所以SpringBoot的啟動類最好放在root package下。
五、SpringBootApplication注解中4個方法
@SpringBootApplication不僅包括上面的三個重要注解,還包含有4個方法:
- Class<?>[] exclude() default {}; 根據Class來排除特定的類加入Spring容器,傳入參數是class類型
- String[] excludeName() default {}; 根據Class name排除特定的類加入spring容器,傳入參數是class的全類名字符串數組
- String[] scanBasePackages() default {};指定掃描包,參數是包名的字符串數組
- Class<?>[] scanBasePackageClasses() default {};指定掃描包,參數是Class類型數組
六、修改組件默認配置
SpringBoot默認會在底層配好所有的組件。但是如果用戶自己配置了以用戶的優先
平時我們都是直接再寫一個bean注入到容器的
其實直接修改配置文件就好了。
原理如下:源碼以HttpEncodingAutoConfiguration為例:
從@EnableConfigurationProperties({ServerProperties.class})可知,該類已經與配置文件綁定了,所以,如果你改變filter.setEncoding(this.properties.getCharset().name());只需要溯源改變server.servlet.encoding.charset的值就可以了
? SpringBoot先加載所有的自動配置類 xxxxxAutoConfiguration
? 每個自動配置類按照條件進行生效,默認都會綁定配置文件指定的值。xxxxProperties里面拿。 xxxProperties和配置文件進行了綁定
? 生效的配置類就會給容器中裝配很多組件
? 只要容器中有這些組件,相當于這些功能就有了
? 定制化配置
? 用戶直接自己@Bean替換底層的組件
? 用戶去看這個組件是獲取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 加載組件 —> xxxxProperties里面拿值 ----> application.properties
參考文章
總結
以上是生活随笔為你收集整理的SpringBoot(2.4.0)自动配置原理(源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网晚报 | 9月20日 星期一 |
- 下一篇: SpringBoot静态资源配置原理(源