1. 程式人生 > 實用技巧 >spring-boot-learning自動配置原理

spring-boot-learning自動配置原理

啟動器:

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
@Import({AutoConfigurationImportSelector.
class}) public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自動配置包
@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 下的所有值。