Spring原始碼閱讀 - @Import 一個繼承 DeferredImportSelector介面的類
阿新 • • 發佈:2022-04-10
1. DeferredImportSelector 介面
具體註釋待續。
類頭註釋的英文翻譯:ImportSelector的一個變體,在處理完所有@Configuration bean之後執行。當所選匯入為@Conditional時,這種型別的選擇器特別有用。
實現也可以擴充套件org.springframework.core.Ordered介面,或者使用org.springframework.core.annotation.Order註解來指示相對於其他DeferredImportSelectors的優先順序。
實現還可以提供一個匯入組,該匯入組可以跨不同選擇器提供額外的排序和過濾邏輯。
作用
- 要匯入的類被延遲匯入
- 匯入組?
public interface DeferredImportSelector extends ImportSelector { /** * Return a specific import group. * <p>The default implementations return {@code null} for no grouping required. * @return the import group class, or {@code null} if none * @since 5.0 */ @Nullable default Class<? extends Group> getImportGroup() { return null; } /** * Interface used to group results from different import selectors. * @since 5.0 */ interface Group { /** * Process the {@link AnnotationMetadata} of the importing @{@link Configuration} * class using the specified {@link DeferredImportSelector}. */ void process(AnnotationMetadata metadata, DeferredImportSelector selector); /** * Return the {@link Entry entries} of which class(es) should be imported * for this group. */ Iterable<Entry> selectImports(); /** * An entry that holds the {@link AnnotationMetadata} of the importing * {@link Configuration} class and the class name to import. */ class Entry { private final AnnotationMetadata metadata; private final String importClassName; public Entry(AnnotationMetadata metadata, String importClassName) { this.metadata = metadata; this.importClassName = importClassName; } /** * Return the {@link AnnotationMetadata} of the importing * {@link Configuration} class. */ public AnnotationMetadata getMetadata() { return this.metadata; } /** * Return the fully qualified name of the class to import. */ public String getImportClassName() { return this.importClassName; } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (other == null || getClass() != other.getClass()) { return false; } Entry entry = (Entry) other; return (this.metadata.equals(entry.metadata) && this.importClassName.equals(entry.importClassName)); } @Override public int hashCode() { return (this.metadata.hashCode() * 31 + this.importClassName.hashCode()); } @Override public String toString() { return this.importClassName; } } } }
2. 解析邏輯
可以看到也是立即被例項化,且並未被注入容器,被放入一個 deferredImportSelectorHandler (可視為一個容器)
org.springframework.context.annotation.ConfigurationClassParser#processImports
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) { // 稍後再處理 this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { // ... } }