Spring Boot 自動裝配原理

ice_image發表於2021-03-16

Spring Boot 自動裝配原理

Spring Boot 在啟動之前還有一系列的準備工作,比如:推斷 web 應用型別,設定初始化器,設定監聽器,啟動各種監聽器,準備環境,建立 applicationContext,準備 context 上下文物件,在 prepareContext 的時候,將 main 函式所在的類(也就是主類)通過 AnnotatedBeanDefinitionReader 注入到 IOC 中,然後 refreshContext 開始重新整理,這裡面會呼叫 AbstractApplicationContext.refresh() 方法。然後就開始了 Spring IOC 的一系列操作。而 Spring Boot 的自動裝配就是在此處展開。

主要是在 ConfigurationClassPostProcessor 類中對其進行的處理,具體的解析邏輯參考07-Spring ConfigurationClassPostProcessor,這裡只說一下在 Spring Boot 中的處理。

在 Spring Boot 中,ConfigurationClassPostProcessor 類的注入是在 createApplicationContext() 中進行的,AnnotationConfigServletWebServerApplicationContext 中的無參構造方法會在 AnnotatedBeanDefinitionReader 建立的時候呼叫 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 將其注入進去。

例項化並且呼叫是在 AbstractApplicationContext 中進行的,最終會在 ConfigurationClassPostProcessor#processConfigBeanDefinitions 呼叫 ConfigurationClassParser#parse 的方法,最後會呼叫 doProcessConfigurationClass 對其各種註解進行解析,在處理 @Import 註解的時候會將 @Import 匯入的類通過 getImports(sourceClass) 方法直接獲得,可以看到 importCandidates 中有四個值,主要的兩個為 AutoConfigurationPackages$Register 和 AutoConfigurationImportSelector,

通過類圖可以看到 AutoConfigurationImportSelector 實現了 DeferredImportSelector 介面,所以在 processImports 中處理的時候,會使用 DeferredImportSelectorHandler#handle 進行處理,將其新增到 deferredImportSelectors 列表中,

解析完成之後,在 ConfigurationClassParser#parse 方法中 this.deferredImportSelectorHandler.process() 進行處理匯入的 AutoConfigurationImportSelector類。使用 DeferredImportSelectorGroupingHandler#processGroupImports() 進行下一步的處理。

grouping.getImports() -> getImports() -> process()。

在 process 方法中會獲取所有自動裝配的 class 物件,呼叫的是 AutoConfigurationImportSelector#getAutoConfigurationEntry 的方法,通過getCandidateConfigurations(annotationMetadata, attributes) 獲取所有的候選配置類,在其中呼叫 SpringFactoriesLoader#LoadFactoryNames 方法獲取。

AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector)deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);
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;
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    ClassLoader classLoaderToUse = classLoader;
    if (classLoaderToUse == null) {
        classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
    }
    String factoryTypeName = factoryType.getName();
    return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
/** 返回SpringFactoriesLoader用來載入候選配置的類 */
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    return EnableAutoConfiguration.class;
}

最終通過 loadSpringFactories 獲取在 META-INF/spring.factories 中所有的配置。

在 configurations = getConfigurationClassFilter().filter(configurations); 中將不符合條件的類過濾掉。

相關文章