1. 程式人生 > 其它 >Spring原始碼閱讀 - @Import 一個繼承 ImportSelector 介面的類

Spring原始碼閱讀 - @Import 一個繼承 ImportSelector 介面的類

處理邏輯在 org.springframework.context.annotation.ConfigurationClassParser#processImports
暫時略其子介面 DeferredImportSelector

1. ImportSelector 介面

selectImports 方法返回的字串陣列,每個字串被視為一個要被注入容器的類的全限定名。

public interface ImportSelector {

    /**
     * Select and return the names of which class(es) should be imported based on
     * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
     * @return the class names, or an empty array if none
     */
    String[] selectImports(AnnotationMetadata importingClassMetadata);

    /**
     * Return a predicate for excluding classes from the import candidates, to be
     * transitively applied to all classes found through this selector's imports.
     * <p>If this predicate returns {@code true} for a given fully-qualified
     * class name, said class will not be considered as an imported configuration
     * class, bypassing class file loading as well as metadata introspection.
     * @return the filter predicate for fully-qualified candidate class names
     * of transitively imported configuration classes, or {@code null} if none
     * @since 5.2.4
     */
    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null;
    }

}

2. 處理邏輯

先例項化這個被匯入的類,然後執行 selectImports,根據全限定名陣列載入 class 陣列,並將這些 class 當做配置類解析一遍。
注意到這個被匯入的類直接被例項化了,BD 沒有注入容器,例項也沒有注入容器。
問題: 匯入的 class 陣列被當做配置類解析,但是沒有被注入容器啊,注入容器的時機在哪?

// Import 的類繼承了 ImportSelector 介面
if (candidate.isAssignable(ImportSelector.class)) {
    // Candidate class is an ImportSelector -> delegate to it to determine imports
    Class<?> candidateClass = candidate.loadClass();
    // 例項化這個類
    ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
            this.environment, this.resourceLoader, this.registry);
    Predicate<String> selectorFilter = selector.getExclusionFilter();
    if (selectorFilter != null) {
        exclusionFilter = exclusionFilter.or(selectorFilter);
    }
    // 繼承了 DeferredImportSelector 介面(ImportSelector 的子介面)
    if (selector instanceof DeferredImportSelector) {
        // ...
    }
    else {
        // 否則立即處理,將返回的字串陣列當做類全限定名陣列,載入對應的 class 入記憶體
        // 傳入的資訊是使用了 @Import 註解的類的資訊
        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
        Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
        // 把這些載入的類當做直接 @Import 的類進行處理,注意到原 @Import 的類並未被注入容器
        processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
    }
}