Springソースコード分析補足1:DeferredImportSelectorの処理

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つのステップがあります。

  1. 異なるDeferredImportSelectorHolderをグループに分割します
  2. 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を参照してください。
侵入がある場合は、連絡して削除してください。コンテンツは、自己記録と学習にのみ使用されます。エラーがあれば訂正してください

おすすめ

転載: blog.csdn.net/qq_36882793/article/details/114300705