锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【spring】DeferredImportSelector的使用与源码分析

时间:2022-10-04 06:30:00 对射光电开关传感器感应开关ex

DeferredImportSelector是ImportSelector既然一个子接口是相似的,那么功能是相似的,都是向的spring容器中注入bean,只不过注入bean时机不同。

DeferredImportSelector与ImportSelector的区别:

  • ImportSelector:顺便处理一下分析配置类。ImportSelector类。
  • DeferredImportSelector:在分析配置类时,只需将其添加到容器中,直到所有配置类分析完成后才能处理DeferredImportSelector。

DeferredImportSelector的使用

自定义DeferredImportSelector当然要实现DeferredImportSelector接口,同时getImportGroup()返回的是一个Group的Class因此,我们还需要定制一个类来实现它DeferredImportSelector.Group当然,接口也不能实现,端倪从源码中可见。

package com.morris.spring.entity.imports;  import com.morris.spring.entity.User; import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.core.type.AnnotationMetadata;  import java.util.ArrayList; import java.util.List;  public class DeferredImportSelectorBean implements DeferredImportSelector { 
          @Override  public Class<? extends Group> getImportGroup() { 
           return DeferredImportSelectorBeanGroup.class;  }   @Override  public String[] selectImports(AnnotationMetadata importingClassMetadata) { 
           return new String[]{ 
        User.class.getName()};
	}

	private static class DeferredImportSelectorBeanGroup implements DeferredImportSelector.Group { 
        

		private final List<Entry> instanceImports = new ArrayList<>();

		@Override
		public void process(AnnotationMetadata metadata, DeferredImportSelector selector) { 
        
			for (String importClassName : selector.selectImports(metadata)) { 
        
				this.instanceImports.add(new Entry(metadata, importClassName));
			}
		}

		@Override
		public Iterable<Entry> selectImports() { 
        
			return instanceImports;
		}
	}
}

使用@Import注解将DeferredImportSelectorBean导入到Spring容器中:

package com.morris.spring.demo.annotation;

import com.morris.spring.entity.User;
import com.morris.spring.entity.imports.DeferredImportSelectorBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import(DeferredImportSelectorBean.class)
public class DeferredImportSelectorBeanDemo { 
        

	public static void main(String[] args) { 
        
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(DeferredImportSelectorBeanDemo.class);
		User user = applicationContext.getBean(User.class);
		System.out.println(user);
		System.out.println(applicationContext.containsBean("deferredImportSelectorBean"));
	}
}

运行结果如下:

User(username=null, age=0)
false

源码分析

DeferredImportSelector的实例化

org.springframework.context.annotation.ConfigurationClassParser#processImports

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
		boolean checkForCircularImports) { 
        
	if (importCandidates.isEmpty()) { 
        
		return;
	}
	if (checkForCircularImports && isChainedImportOnStack(configClass)) { 
        
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else { 
        
		this.importStack.push(configClass);
		try { 
        
			for (SourceClass candidate : importCandidates) { 
        
				if (candidate.isAssignable(ImportSelector.class)) { 
        
					// 处理ImportSelector
					// Candidate class is an ImportSelector -> delegate to it to determine imports
					Class<?> candidateClass = candidate.loadClass(); // 加载ImportSelector
					ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
							this.environment, this.resourceLoader, this.registry); // 反射实例化ImportSelector
					Predicate<String> selectorFilter = selector.getExclusionFilter();
					if (selectorFilter != null) { 
        
						exclusionFilter = exclusionFilter.or(selectorFilter);
					}
					if (selector instanceof DeferredImportSelector) { 
        
						// 特殊处理DeferredImportSelector
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					}
					else { 
        
						// 调用selectImports方法
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
						// 又递归,实际上会进入下面的else
						processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
					}
				}
... ...

收集DeferredImportSelector

DeferredImportSelectorHandler#handle方法只是负责DeferredImportSelector的收集,加入到deferredImportSelectors容器中。
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#handle

private class DeferredImportSelectorHandler { 
        
	@Nullable
	private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
	/** * Handle the specified {@link DeferredImportSelector}. If deferred import * selectors are being collected, this registers this instance to the list. If * they are being processed, the {@link DeferredImportSelector} is also processed * immediately according to its {@link DeferredImportSelector.Group}. * @param configClass the source configuration class * @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 { 
        
			// 这里只是加入到list中
			this.deferredImportSelectors.add(holder);
		}
	}
... ...

DeferredImportSelector的调用

ConfigurationClassParser#parse主要负责对所有的配置类进行解析,解析完成最后会完成DeferredImportSelector的调用。
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set)

public void parse(Set<BeanDefinitionHolder> configCandidates) { 
        
	// 开始遍历所有的BD,解析其中的各种注解
	for (BeanDefinitionHolder holder : configCandidates) { 
        
		BeanDefinition bd = holder.getBeanDefinition();
		try { 
        
			if (bd instanceof AnnotatedBeanDefinition) { 
        
				// 有注解的BD具体的实现类为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);
		}
	}

	// DeferredImportSelector的处理
	this.deferredImportSelectorHandler.process();
}

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process

public void process() { 
        
	List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
	this.deferredImportSelectors = null;
	try { 
        
		if (deferredImports != null) { 
        
			DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
			// 对DeferredImportSelector进行排序,DeferredImportSelector可以实现order,@Order,@Priority等
			deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
			// 将group注册到groupings
			// 将配置类注册到configurationClasses
			deferredImports.forEach(handler::register);
			handler.processGroupImports();
		}
	}
	finally { 
        
		this.deferredImportSelectors = new ArrayList<>();
	}
}

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#register

private class DeferredImportSelectorGroupingHandler { 
        
	private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();
	private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
	public void register(DeferredImportSelectorHolder deferredImport) { 
        
		Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
		// Map.computeIfAbsent,key存在就返回value,key不存在就根据function计算后插入map中,并返回value
		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());
	}

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports

public void processGroupImports() { 
        
	for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { 
        
		Predicate<String> exclusionFilter = grouping.getCandidateFilter();
		// grouping.getImports()会完成group的两个方法的调用
		grouping.getImports().forEach(entry -> { 
        
			ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
			try { 
        
				// 将grouping.getImports()返回的类当成import普通的bean来处理
				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);
			}
		});
	}
}

org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports

public Iterable<Group.Entry> getImports() { 
        
	for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { 
        
		// 先调用Group的process方法
		this.group.process(deferredImport.getConfigurationClass().getMetadata(),
				deferredImport.getImportSelector());
	}
	// 再调用Group的selectImports方法
	return this.group.selectImports();
}
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章