記事のディレクトリ
I.はじめに
このシリーズは、ソースコード分析をレビューする過程で欠落しているコンテンツの補足です。コンテンツは、個人の学習記録にのみ使用されます。
で春のソースコード分析デリバティブパート7:ConfigurationClassPostProcessorパートI、我々はConfigurationClassPostProcessorでImportSelectorとDeferredImportSelectorの分析が完了について話しました。
ImportSelectorの呼び出しは、ImportSelector#selectImportsメソッドを直接呼び出して分析を完了することですが、DeferredImportSelectorの呼び出しはそれほど単純ではありません。この記事では、DeferredImportSelectorの呼び出しプロセスを分析します。
二、DeferredImportSelector
DeferredImportSelector
これはImportSelector
サブインターフェイスインターフェイスです。
DeferredImportSelector
2つの特徴があります:
- このインターフェースを継承するImportSelectorは、すべての@Configuration構成クラスが処理された後に実行されます。これは
ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
、他の候補が解析されるまでthis.deferredImportSelectorHandler.process();
、解決するためにクラス構成メソッドが呼び出されるためです。DeferredImportSelector
- 複数のDeferredImportSelectorが定義されている場合は、並べ替えにOrderインターフェイスが使用されます。これも
this.deferredImportSelectorHandler.process();
ソートされた呼び出しです。
Sikeソースシリーズによって[解決]主要なImportSelectorインターフェイスワード:
DeferredImportSelectorインターフェースは、ImportSelectorインターフェースのサブインターフェースです。このインターフェースは、すべての@Configuration構成クラス(spring.factoriesファイルの構成クラスである自動構成クラスを除く)が処理された後、セレクターと@条件付き条件付きアノテーションは一緒に使用する場合に特に便利です。このインターフェースは、複数のセレクターの優先順位を定義するために、インターフェースOrderedまたは@Orderedとともに使用することもできます。
3、ソースコード分析
1.DeferredImportSelectorの前処理
DeferredImportSelectorには後処理機能があるため、最初にDeferredImportSelectorをスキャンしたときにすぐに処理することはできません。最後に、統一された方法で保存および処理する必要があります。
ConfigurationClassParser#processImportsでのDeferredImportSelectorの処理は次のとおりです。
// deferredImportSelectorHandler 为 org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler
// 这一步实际上是将 configClass 和 selector 保存到了一个集合(deferredImportSelectors)中,集合(deferredImportSelectors)标记着待处理的selector
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
具体的な実装は次のとおりです。
// ConfigurationClassParser.DeferredImportSelectorHandler#handle
// deferredImportSelectors 保存待处理的 Selector
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
// configClass 是持有该@Import 注解的 配置类, importSelector 是引入的 DeferredImportSelector
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
// 将 DeferredImportSelector 和其引入的配置类保存起来。
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
// 如果deferredImportSelectors 为空,则重新注册
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
// 将当前的 config 和 Selector 的持有者保存起来
this.deferredImportSelectors.add(holder);
}
}
2.DeferredImportSelectorの実際の処理
ではConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
最後の文DeferredImportSelectorを扱っ
this.deferredImportSelectorHandler.process();
詳細な実装は次のとおりです。
public void process() {
// 获取待处理的 DeferredImportSelectorHolder
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
// 排序
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
// 1. 根据不同的group 进行分组注册
deferredImports.forEach(handler::register);
// 2. 按照分组调用
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
2.1ハンドラー::レジスタ
ここには2つのステップがあります。
- 異なるDeferredImportSelectorHolderをグループに分割します
- DeferredImportSelectorHolderの情報をconfigurationClassesに保存します。(後で電話するときに取得します)
public void register(DeferredImportSelectorHolder deferredImport) {
// 获取当前 DeferredImportSelector 的Group
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
// 将当前 DeferredImportSelector 添加到同一分组中的
grouping.add(deferredImport);
// 保存需要处理的配置类
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
2.2 handler.processGroupImports()
このステップでは、グループ内のDeferredImportSelectorによって導入されたクラスが、さまざまなグループに従ってentry.getImportClassName()によってラップされ、次にprocessImportsメソッドが呼び出されて新しい分析ラウンドが行われます。
public void processGroupImports() {
// 遍历每个分组
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
// 获取分组的过滤器
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
// 遍历分组中所有的 Entry (封装了需要引入的类的信息)
grouping.getImports().forEach(entry -> {
// 从 configurationClasses 集合中获取到对应的 ConfigurationClass 。其中保存
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
// 对 configurationClass 进行解析。这里的解析在 ConfigurationClassPostProcessor 文章已经有过解释。
// entry.getImportClassName() 获取到了引入的类
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);
}
});
}
}
これgrouping.getImports()
は次のことを達成することです
// org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 调用 DeferredImportSelector.Group#process
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
// 调用 DeferredImportSelector.Group#selectImports
return this.group.selectImports();
}
ここで呼んでいるのは DefaultDeferredImportSelectorGroup
private static class DefaultDeferredImportSelectorGroup implements Group {
private final List<Entry> imports = new ArrayList<>();
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
// 调用了ImportSelector#selectImports 方法
for (String importClassName : selector.selectImports(metadata)) {
this.imports.add(new Entry(metadata, importClassName));
}
}
@Override
public Iterable<Entry> selectImports() {
// 直接将 Imports 返回
return this.imports;
}
}
要約すると、DeferredImportSelectorの処理は、ImportSelector#selectImportsメソッドを直接呼び出すことではないことがわかります。代わりに、DeferredImportSelector.Group#processメソッドとGroup#selectImportsメソッドを呼び出して、インポート機能を完了します。
上:内容については、
https://mingyang.blog.csdn.net/article/details/108861935を参照してください。
侵入がある場合は、連絡して削除してください。コンテンツは、自己記録と学習にのみ使用されます。エラーがあれば訂正してください