spring-boot-learning自動配置原理
阿新 • • 發佈:2020-08-18
啟動器:
spring-boot-starter:spring-boot場景啟動器,幫我們倒入我們場景需要的元件依賴不同的場景有不同的啟動器:
spring-boot-starter-web 主程式類,主入口類:@SpringBootApplication public class DoneApplication { public static void main(String[] args) { SpringApplication.run(DoneApplication.class, args); } }
@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,SpringBoot就應該執行這個類的main方法來啟動SpringBoot應用;
這個註解的詳如下:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {
@SpringBootConfiguration springboot的配置類的註解,標註在某個類上,表示這是一個Spring Boot的配置類
@EnableAutoConfiguration 開啟自動配置,告訴SpringBoot開啟自動配置功能,詳解如下:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage@AutoConfigurationPackage:自動配置包@Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration {
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage {
@Import(Registrar.class):
Spring的底層註解@Import,給容器中匯入一個元件;匯入的元件由 Registrar.class;
將主配置類(@SpringBootApplication:標註的類)的所在包及下面所有子包裡面的所有元件掃描到容器
AutoConfigurationImportSelector 類的作用就是往 Spring 容器中匯入元件,匯入哪些元件的選擇器
將所有需要匯入的元件以全類名的方式返回;這些元件就會被新增到容器中;
會給容器中匯入非常多的自動配置類(xxxAutoConfiguration);就是給容器中匯入這個場景需要的所有元件, 並配置好這些元件;
流程;
@SpringbootApplication註解--@EnableAutoConfiguration--@Import(AutoConfigurationImportSelector.class)重要就是這個類
AutoConfigurationImportSelector這個類有個方法:
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
AutoConfigurationImportSelector 的 selectImports 就是用來返回需要匯入的元件的全類名陣列的
就是通過方法getAutoConfigurationEntry方法
getCandidateConfigurations方法裡面
SpringFactoriesLoader裡面函式loadFactoryNames
loadFactoryNames裡面的
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryTypeName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryImplementationName = var9[var11]; result.add(factoryTypeName, factoryImplementationName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
1111獲取配置檔案資訊:
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
2222通過函式loadSpringFactories獲取一個map集合:
private static Map<String, List<String>> loadSpringFactories
先尋找傳入了什麼
回到選擇器:
333從返回的 Map 中通過剛才傳入的 EnableAutoConfiguration.class
引數,獲取該 key 下的所有值。