一、自動配置原理
1、原理圖
www.processon.com/diagraming/6072e...
2、原始碼入手
- SpringBootApplication
註解說明:
@Target(ElementType.TYPE)//設定當前註解可以標註在哪
@Retention(RetentionPolicy.RUNTIME)//標註註解的類編譯以什麼方式保留–執行時類,會被jvm載入
@Documented //生成java doc註解資訊
@Inherited //是否會被繼承
@SpringBootConfiguration //標註在某個類上,標識這是一個SpringBoot配置類
@EnableAutoConfiguration //標識這是一個配置類;配置類也是容器中的一個元件
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), //掃描包
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
FilterType:spring對外提供的擴充套件類,可以按照我們的意願進行排除
AutoConfigurationExcludeFilter:排除所有配置類並且是自動配置類中裡面的其中一個
我們進入註解—>@EnableAutoConfiguration
@AutoConfigurationPackage,作用是將當前配置類所在的包儲存在BasePackages的Bean中,供Spring內部使用
@Import 關鍵註解
可以看到,在@EnableAutoConfiguration註解內使用到了@import註解來完成匯入配置的功能,而EnableAutoConfigurationImportSelector 實現了DeferredImportSelectorSpring內部在解析@Import註解時會呼叫getAutoConfigurationEntry方法
如下程式碼的getCandidateConfigurations方法
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations方法中的SpringFactoriesLoader.loadFactoryNames.loadFactoryNames.loadSpringFactories方法中進行掃描具有META-INF/spring.factories檔案的jar包。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
@EnableAutoConfiguration註解通過@SpringBootApplication被間接的標記在了Spring Boot的啟動類上。在SpringApplication.run(…)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類載入到Spring容器中
如下為SpringBoot自動配置原理圖
本作品採用《CC 協議》,轉載必須註明作者和本文連結