简介
DeferredImportSelector
延迟导入选择器是Spring提供的一个扩展导入器,该导入器是ImportSelector
的一个变体,该导入器是在处理配置类上@Import
注解的时候注册的,当所有{@code @Configuration}
配置类解析完成后才会运行所有被注册的DeferredImportSelector
。
该导入器的主要作用是,委托Group
接口导入一组配置类。Springboot 的AutoConfigurationImportSelector
实现了该接口,用于自动装配类的获取。请查看《Springboot源码-自动装配(一):AutoConfigurationImportSelector》
DeferredImportSelector接口
DeferredImportSelector继承自ImportSelector,扩展了getImportGroup方法,getImportGroup方法返回同一个Group类的DeferredImportSelector会被分到同一个组中。当所选导入是{@code @Conditional}时,这种类型的选择器可能特别有用,可能就是不同的Condition对应不同的DeferredImportSelector实现。
/*** {@link ImportSelector} 的变体,在解析完所有 {@code @Configuration} bean后运行。* 当所选导入是{@code @Conditional}时,这种类型的选择器可能特别有用。** <p>实现还可以扩展 {@link org.springframework.core.Ordered} 接口* 或使用 {@link org.springframework.core.annotation.Order} 注解来指示相对于其他 {@link DeferredImportSelector DeferredImportSelectors} 的优先级。* * <p>Springboot {@link org.springframework.boot.autoconfigure.AutoConfigurationImportSelector}实现了该接口,用于自动装配类的获取*/
public interface DeferredImportSelector extends ImportSelector {/*** 对不同导入选择器的导入结果进行分组的接口。** @return DeferredImportSelector所属的Group对象。* @since 5.0*/@Nullabledefault Class<? extends Group> getImportGroup() {return null;}
}
Group接口
group接口主要用于对DeferredImportSelector进行分组,遍历Group对应的DeferredImportSelector对象集合,依次执行Group的process方法处理对应的逻辑。然后利用selectImports方法将process处理后的结果已Entry的形式返回回来。Springboot自动装配类AutoConfigurationImportSelector实现了该process接口,主要用于读取Springboot的自动装配类。以下是Springboot实现该接口的具体类和方法。请看《Springboot源码-自动装配(一):AutoConfigurationImportSelector》
/*** 对不同导入选择器的导入结果进行分组的接口。** 也就是说一个Group可以对应多个DeferredImportSelector,DeferredImportSelector的getImportGroup方法返回同一个Group类,则会将这些DeferredImportSelector对象分到同一个组中。** <p> Springboot@{@link org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup}实现了该接口* 用于获取所有的自动装配类*** @since 5.0*/
interface Group {/*** 根据标注了@Import注解的配置类的注解元数据来执行DeferredImportSelector进行配置类的导入* * <p>* 1.Springboot自动装配类AutoConfigurationImportSelector实现了该process接口,主要用于读取Springboot的自动装配类。以下是Springboot实现该接口的具体类和方法** @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process* @param metadata 标注了@Import注解的配置类的注解元数据*/void process(AnnotationMetadata metadata, DeferredImportSelector selector);/*** 返回包含导入配置类的全限定名和该配置类的注解元数据的{@link Entry}集合*/Iterable<Entry> selectImports();/*** 包含导入配置类的全限定名和该配置类的注解元数据的{@link Entry}*/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;}@Overridepublic 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));}@Overridepublic int hashCode() {return (this.metadata.hashCode() * 31 + this.importClassName.hashCode());}@Overridepublic String toString() {return this.importClassName;}}
}
DeferredImportSelectorHandler处理器
- DeferredImportSelectorHandler利用handle方法收集所有的DeferredImportSelector封装成DeferredImportSelectorHolder放入到list集合中。
- DeferredImportSelectorHandler利用process方法获取所有的导入类。
代码详细逻辑如下:
- 利用handle收集所有的DeferredImportSelector封装成DeferredImportSelectorHolder放入到list集合中。
- 执行类的导入
- 创建DeferredImportSelectorGroupingHandler对象
- 遍历所有的DeferredImportSelector对象,依次调用DeferredImportSelectorGroupingHandler的register方法向DeferredImportSelectorGroupingHandler中保存Group与该Group下所有DeferredImportSelector映射关系
- 执行DeferredImportSelectorGroupingHandler的processGroupImports方法进行类的导入
private class DeferredImportSelectorHandler {@Nullableprivate List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();/*** {@link DeferredImportSelector}的注册阶段* 处理指定的{@link DeferredImportSelector}.* 如果deferredImportSelector等于null,则说明{@link DeferredImportSelector}正在被收集,注册器将会将{@link DeferredImportSelector}注册到当前对象的list中* 如果deferredImportSelector不等于null,如果{@link DeferredImportSelector}正在被处理,则{@link DeferredImportSelector}也会根据其{@link DeferredImportSelector.Group}立即进行处理。** @param configClass Import注解标注的配置类* @param importSelector the selector to handle*/public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);if (this.deferredImportSelectors == null) {DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();handler.register(holder);handler.processGroupImports();} else {this.deferredImportSelectors.add(holder);}}/*** {@link DeferredImportSelector}的执行阶段阶段* 1.执行DeferredImportSelector的getImportSelector获取导入组Group* 2.实例化获取到的导入组Group* 3.执行导入组Group的getImports方法获取所有的导入的配置类* 4.调用{@link ConfigurationClassParser#processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}方法处理配置类*/public void process() {List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;this.deferredImportSelectors = null;try {if (deferredImports != null) {DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);deferredImports.forEach(handler::register);handler.processGroupImports();}} finally {this.deferredImportSelectors = new ArrayList<>();}}
}
DeferredImportSelectorGroupingHandler处理器
DeferredImportSelectorGroupingHandler
处理器主要用于接受Group
和DeferredImportSelector
的注册,然后将每一个Group与其对应的所有DeferredImportSelector
的对应关系保存起来,然后调用processGroupImports
方法遍历每一个Group
,执行组内的所有DeferredImportSelector
,来获取所有的导入类。获取到的导入类会再次通过ConfigurationClassParser#processImports
方法进行处理。
private class DeferredImportSelectorGroupingHandler {private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();/*** 注册Group对象** @param deferredImport DeferredImportSelector对象的包装器对象*/public void register(DeferredImportSelectorHolder deferredImport) {//获取DeferredImportSelector对应的导入Group对象,Springboot的自动配置类的导入就是基于该接口进行注册的Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();//将Group对象放入当前对象的Map中,后续交由下边的processGroupImports方法进行配置类的处理DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent((group != null ? group : deferredImport),key -> new DeferredImportSelectorGrouping(createGroup(group)));grouping.add(deferredImport);this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),deferredImport.getConfigurationClass());}/*** 调用processImports方法处理Group对象返回的所有导入配置类*/public void processGroupImports() {for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {Predicate<String> exclusionFilter = grouping.getCandidateFilter();//获取所有的自动配置类,方式有://1.又Springboot实现,功能为加载所有的自动配置类grouping.getImports().forEach(entry -> {ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());try {//处理所有的导入配置类processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),exclusionFilter, false);} catch (BeanDefinitionStoreException ex) {throw ex;} catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configurationClass.getMetadata().getClassName() + "]", ex);}});}}/*** 实例化Group对象** @param type Group的类* @return 实例化Group对象*/private Group createGroup(@Nullable Class<? extends Group> type) {Class<? extends Group> effectiveType = (type != null ? type : DefaultDeferredImportSelectorGroup.class);return ParserStrategyUtils.instantiateClass(effectiveType, Group.class,ConfigurationClassParser.this.environment,ConfigurationClassParser.this.resourceLoader,ConfigurationClassParser.this.registry);}
}
DeferredImportSelector持有器
private static class DeferredImportSelectorHolder {private final ConfigurationClass configurationClass;private final DeferredImportSelector importSelector;public DeferredImportSelectorHolder(ConfigurationClass configClass, DeferredImportSelector selector) {this.configurationClass = configClass;this.importSelector = selector;}public ConfigurationClass getConfigurationClass() {return this.configurationClass;}public DeferredImportSelector getImportSelector() {return this.importSelector;}
}
DeferredImportSelectorGrouping
遍历Group集合,然后执行每一个Group中的每一个DeferredImportSelector获取导入类。
private static class DeferredImportSelectorGrouping {private final DeferredImportSelector.Group group;private final List<DeferredImportSelectorHolder> deferredImports = new ArrayList<>();DeferredImportSelectorGrouping(Group group) {this.group = group;}public void add(DeferredImportSelectorHolder deferredImport) {this.deferredImports.add(deferredImport);}/*** <pre>* 1.实现1* @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process* 2.实现2* @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#selectImports** </pre>* <p>* <p>* Return the imports defined by the group.** @return each import with its associated configuration class*/public Iterable<Group.Entry> getImports() {for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {/** 功能实现1:加载Springboot自动配置类*/this.group.process(deferredImport.getConfigurationClass().getMetadata(),deferredImport.getImportSelector());}/** 功能实现1:对加载进来的Springboot自动配置类进行处理,包含过滤掉排除的自动配置类、对配置类进行排序*/return this.group.selectImports();}public Predicate<String> getCandidateFilter() {Predicate<String> mergedFilter = DEFAULT_EXCLUSION_FILTER;for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {Predicate<String> selectorFilter = deferredImport.getImportSelector().getExclusionFilter();if (selectorFilter != null) {mergedFilter = mergedFilter.or(selectorFilter);}}return mergedFilter;}
}