@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接口的类,这样就实现了延迟加载。