Spring源码阅读 - @Import 一个继承 DeferredImportSelector接口的类
1. DeferredImportSelector 接口
具体注释待续。
类头注释的英文翻译:ImportSelector的一个变体,在处理完所有@Configuration bean之后运行。当所选导入为@Conditional时,这种类型的选择器特别有用。
实现也可以扩展org.springframework.core.Ordered接口,或者使用org.springframework.core.annotation.Order注解来指示相对于其他DeferredImportSelectors的优先级。
实现还可以提供一个导入组,该导入组可以跨不同选择器提供额外的排序和过滤逻辑。
作用
- 要导入的类被延迟导入
- 导入组?
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. deferredImportSelectorHandler.handle & DeferredImportSelectorHandler
private class DeferredImportSelectorHandler {
/**
* 类似 BeanDefinitionHolder, 对 DeferredImportSelector 和 ConfigurationClass 封装一下
*/
@Nullable
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
// emm, 这是考虑到并发处理吗, 感觉好像也不对, 如果在 process 中, 则立即处理
if (this.deferredImportSelectors == null) {
// 实际上这里的逻辑和 process 是一致的
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
// 否则添加等待批量处理
this.deferredImportSelectors.add(holder);
}
}
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
// 这个应该是处理器
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
// 每一个进行 register
deferredImports.forEach(handler::register);
// 然后批量处理
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
4. 实际处理流程 DeferredImportSelectorGroupingHandler
由上面可看出先对每个 selector 执行 DeferredImportSelectorGroupingHandler#register,然后批量处理 DeferredImportSelectorGroupingHandler#processGroupImports
暂略,因为还不知道 group 的作用
5. 实际调用时机
由上面可看出 handle 会将 DeferredImportSelector 暂时存储,还未执行。
ConfigurationClassParser 处理配置类就是这个,而这个方法只会被 org.springframework.context.annotation.ConfigurationClassPostProcessor 调用,如果我们传入一个启动类,那么当这个启动类被处理完毕,才会执行 process。
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 一般是进入这里,其他的暂略
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}