SpringBoot快速入门-DeffredImportSelector详解

@ImportSelector引入一组Bean,但是无法控制相同功能类的引入顺序,@DeffredImportSelector 可以控制相同功能类的引入顺序、延时加载和分组,是Spring Boot自动装配原理中不可获的重要功能。

我们先来定一个最简单的demo,代码:

import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.util.function.Predicate;

/**
 * www.itzhimei.com
 * DeferredImportSelector 定义
 */
public class MyDeferredImport implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        System.out.println("-----------my deferred selectImports----------");
        return new String[0];
    }

    @Override
    public Predicate<String> getExclusionFilter() {
        return null;
    }

    @Override
    public Class<? extends Group> getImportGroup() {
        System.out.println("-----------my deferred getImportGroup----------");
        return null;
    }
}
/* 输出
-----------my deferred getImportGroup----------
-----------my deferred selectImports----------
 */

从输出结果,我们可以看出,在调用实现了DeffredImportSelector接口的类时,先调用getImportGroup方法,如果getImportGroup方法为空则调用selectImport方法。

我们再来实现一个demo,让getImportGroup方法返回不为空,代码:

/**
 * www.itzhimei.com
 * DeferredImportSelector 定义
 */
public class MyDeferredImport2 implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        System.out.println("-----------my deferred selectImports----------");
        return new String[]{"com.itzhimei.handle.Person9"};
    }

    @Override
    public Predicate<String> getExclusionFilter() {
        return null;
    }

    @Override
    public Class<? extends Group> getImportGroup() {
        System.out.println("-----------my deferred getImportGroup----------");
        return MyGroup.class;
    }

    private static class MyGroup implements DeferredImportSelector.Group{

        AnnotationMetadata metadata;

        @Override
        public void process(AnnotationMetadata metadata,DeferredImportSelector selector){
            this.metadata = metadata;
        }

        @Override
        public Iterable<Entry> selectImports() {
            System.out.println("-----------my deferred Group getImportGroup----------");
            List<Entry> list = new ArrayList<>();
            list.add(new Entry(this.metadata,"com.itzhimei.handle.Person9"));
            return list;
        }
    }
}
/* 输出
-----------my deferred getImportGroup----------
-----------my deferred Group getImportGroup----------
 */

从数据结果可以看出,如果getImportGroup方法不为空则调用先执行getImportGroup,就不再执行selectImport方法了。

上面的执行逻辑其实是Spring在控制的,因为Bean的加载本来就是Spring的工作。

到这里你可能有个问题,DeffredImportSelector是如何实现延迟加载的呢?延迟加载不是DeffredImportSelector直接控制的,而是Spring框架进行对象加载的时候,是Spring控制的。
大概的顺序如下:
1、先加载@Configuration注解的类
2、加载@Import的类
3、加载@ImportResource的类
4、加载父类方法等
以上都加载完成,才会加载实现了DeffredImportSelector接口的类,这样就实现了延迟加载。