Spring创建Bean源码 - 解析配置类: 延迟导入选择器DeferredImportSelector
简介
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
*/
@Nullable
default 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;
}
@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;
}
}
}
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 {
@Nullable
private 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;
}
}