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

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

1. DeferredImportSelector 介面

具體註釋待續。
類頭註釋的英文翻譯:ImportSelector的一個變體,在處理完所有@Configuration bean之後執行。當所選匯入為@Conditional時,這種型別的選擇器特別有用。
實現也可以擴充套件org.springframework.core.Ordered介面,或者使用org.springframework.core.annotation.Order註解來指示相對於其他DeferredImportSelectors的優先順序。
實現還可以提供一個匯入組,該匯入組可以跨不同選擇器提供額外的排序和過濾邏輯。
作用

  1. 要匯入的類被延遲匯入
  2. 匯入組?
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 {
        // ...
    }
}

3. 執行時機/匯入時機