SpringBoot自動配置
SpringBoot 自動配置的原理是什么?
Spring在啟動的時候會自動掃描外部jar包中的META-INF\spring.factories,將文件中的配置類型信息加載到Spring容器,并且執行類中定義的操作。對于外部的jar包來說,只要遵循SpringBoot的標準來,就能將自己的功能配置到SpringBoot中。
SpringBoot 3.0版本開始,自動配置包的路徑就將META-INF\spring.factories改成了META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports
SpringBoot 是如何實現自動配置的?
SpringBoot自動配置主要是通過@EnableAutoConfiguratio注解實現的,這個注解包含了@Import(AutoConfigurationImportSelector.class)注解,作用是在啟動的時候會自動掃描外部jar的classPath下的所有META-INF\spring.factories(以SpringBoot 2.0為例),根據文件中的指定配置類加載相應的Bean自動配置。
(1)@SpringBootApplication
我們來看看@SpringBootApplication注解的源代碼注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// CODE...
}
@SpringBootConfiguration:允許上下文額外注入的bean或者導入其他配置類@EnableAutoConfiguration:啟動自動配置的機制@ComponentScan:掃描被@Component/@Service/@Controller注解的 bean,注解會默認掃描包下的所有 bean,可以自定義哪些不被掃描,例如TypeExcludeFilter, AutoConfigurationExcludeFilter

現在,我們重點關注@EnableAutoConfiguration注解
(2)@EnableAutoConfiguration
要了解該注解的工作機制,我們首先要從源碼開始
源碼:
...
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// CODE...
}
@AutoConfigurationPackage:負責注冊主配置所在包以及子包到Spring容器下@Import(AutoConfigurationImportSelector.class):導入自動配置選擇器,負責加載和過濾所有自動配置類
(3)AutoConfigurationImportSelector -- 自動配置導入選擇器
1)AutoConfigurationImportSelector的繼承體制如下:

2)入口函數--selectImports()
功能:獲取所有符合條件的類的全限定類名,并將這些類需要的加載到IOC容器中

3)核心實現--加載自動配置類
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 1. 獲取注解屬性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 2. 加載候選配置類
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 3. 去重
configurations = removeDuplicates(configurations);
// 4. 獲取排除的配置
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 5. 檢查排除的類是否有效
checkExcludedClasses(configurations, exclusions);
// 6. 移除排除的配置
configurations.removeAll(exclusions);
// 7. 過濾配置(條件注解處理)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 觸發事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
關鍵點說明:
獲取所有自動裝配的配置類,讀取META-INF\spring.factories
// 2. 加載候選配置類
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
留下需要的配置類:
經過getCandidateConfigurations讀取META-INF\spring.factories獲取到所有自動裝配的配置類之后,由于加載太多的配置類會影響Spring容器的性能,因此需要對這些配置類進行排除過濾。
// 4. 獲取排除的配置
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 5. 檢查排除的類是否有效
checkExcludedClasses(configurations, exclusions);
// 6. 移除排除的配置
configurations.removeAll(exclusions);
// 7. 過濾配置(條件注解處理)
configurations = getConfigurationClassFilter().filter(configurations);
實操一遍:
1)判斷自動配置是否打開

2)獲取@EnableAutoConfiguration注解中的exclude和excludeName
...
public @interface EnableAutoConfiguration {
// 排除特定的自動配置類,確保永遠不會被應用
Class<?>[] exclude() default {};
// 排除特定的自動配置類名,確保永遠不會被應用
String[] excludeName() default {};
}
效果如下

3)獲取所有自動裝配的配置類,讀取META-INF\spring.factories

4)去重removeDuplicates(configurations)
通過哈希集合LinkedHashSet<>()去掉重復的配置類
5)獲取排除的配置類
比如我們在配置文件中寫上:
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
指 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration是要被排出的

說明已經排除成功
6)檢查是否排除生效 -- checkExcludedClasses(configurations, exclusions)
7)移除要排除的配置類 -- configurations.removeAll(exclusions)
8)過濾出需要的配置類 -- 按需加載

9)觸發自動導入事件
fireAutoConfigurationImportEvents(configurations, exclusions)
總結
SpringBoot通過@EnableAutoConfiguration注解自動裝配,使用SpringFactoriesLoader加載META-INF/spring.factories中的自動裝配的配置類。
end...

浙公網安備 33010602011771號