Suplemento uno del análisis del código fuente de Spring: Procesamiento de DeferredImportSelector

I. Introducción

Esta serie es un complemento de algunos contenidos que faltan en el proceso de revisión del análisis del código fuente. El contenido solo se utiliza para registros de aprendizaje personales.


En Spring Source Code Analysis Derivative Part Seven: ConfigurationClassPostProcessor Part I , hablamos sobre la finalización del análisis de ImportSelector y DeferredImportSelector en ConfigurationClassPostProcessor.
La llamada a ImportSelector es para llamar directamente al método ImportSelector # selectImports para completar el análisis, pero la llamada a DeferredImportSelector no es tan sencilla. Este artículo analiza el proceso de llamada de DeferredImportSelector.

二 、 DeferredImportSelector

DeferredImportSelectorEs una ImportSelectorinterfaz de subinterfaz.

DeferredImportSelector Hay dos características:

  • ImportSelector que hereda esta interfaz se ejecutará después de que se procesen todas las clases de configuración de @Configuration. Esto se debe a que ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)hasta que se analicen los otros candidatos, se llamará this.deferredImportSelectorHandler.process();al método de configuración de clase para resolverDeferredImportSelector
  • Si se define más de un DeferredImportSelector, la interfaz Order se utiliza para ordenar. Esto también está en una this.deferredImportSelectorHandler.process();llamada ordenada.

Por la serie de fuentes de Sike [resolver] el principio de las palabras de la interfaz ImportSelector :

La interfaz DeferredImportSelector es una subinterfaz de la interfaz ImportSelector. Esta interfaz se ejecutará después de que se procesen todas las clases de configuración de @Configuration (excluidas las clases de configuración automatizadas, que son las clases de configuración en el archivo spring.factories); cuando el selector y @ Las anotaciones condicionales condicionales están juntas Es particularmente útil cuando se usa. Esta interfaz también se puede usar con la interfaz Ordered o @Ordered para definir la prioridad de múltiples selectores

Tres, análisis de código fuente

1. Procesamiento previo de DeferredImportSelector

Debido a que DeferredImportSelector tiene funciones de posprocesamiento, no se puede procesar inmediatamente cuando se escanea DeferredImportSelector al principio. Debe guardarse y procesarse de manera unificada al final.
El procesamiento de DeferredImportSelector en ConfigurationClassParser # processImports es el siguiente:

// deferredImportSelectorHandler  为 org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler
	// 这一步实际上是将 configClass 和 selector 保存到了一个集合(deferredImportSelectors)中,集合(deferredImportSelectors)标记着待处理的selector
	this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);

La implementación específica es la siguiente:

	// 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. El procesamiento real de DeferredImportSelector

En ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)la última oración tratada DeferredImportSelector

	this.deferredImportSelectorHandler.process();

La implementación detallada es la siguiente:

	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 manejador :: registro

Aquí hay dos pasos:

  1. Dividir diferentes DeferredImportSelectorHolder en grupos
  2. Guarde la información de DeferredImportSelectorHolder en configurationClasses. (Obtener cuando llame más tarde)
	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 ()

En este paso, la clase introducida por DeferredImportSelector en el grupo es envuelta por entry.getImportClassName () según diferentes grupos, y luego se llama al método processImports para una nueva ronda de análisis.

	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);
				}
			});
		}
	}

Que grouping.getImports()es lograr lo siguiente

	// 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();
	}

Lo que llamamos aquí es 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;
		}
	}


En resumen, podemos ver que el procesamiento de DeferredImportSelector no es llamar directamente al método ImportSelector # selectImports. En su lugar, llama a los métodos DeferredImportSelector.Group # process y Group # selectImports para completar la función de importación.


Arriba: Para ver el contenido, consulte
https://mingyang.blog.csdn.net/article/details/108861935.
Si hay alguna intrusión, comuníquese con ella y elimínela. El contenido solo se utiliza para la autograbación y el aprendizaje. Si hay algún error, corrígeme

Supongo que te gusta

Origin blog.csdn.net/qq_36882793/article/details/114300705
Recomendado
Clasificación