2、SpringBoot之Spi机制加载Spring.factories

 当前文章分析的核心是:解析启动类@Import时获取得到的 AutoConfigurationImportSelector

DeferredImportSelector:A variation of {@link ImportSelector} that runs after all {@code @Configuration} beans have been processed. This type of selector can be particularly useful when the selected imports are {@code @Conditional}。

解决 Spring Boot 中不能被默认路径扫描的配置类的方式,有 2 种:

(1)在 Spring Boot 主类上使用 @Import 注解。
(2)使用 spring.factories 文件。

1、DeferredImportSelectorHandler

private class DeferredImportSelectorHandler {

	@Nullable
	private List deferredImportSelectors = new ArrayList<>();

	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 {
			this.deferredImportSelectors.add(holder);
		}
	}

	public void process() {
		List deferredImports = this.deferredImportSelectors;
		this.deferredImportSelectors = null;
		try {
			if (deferredImports != null) {
				DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
				deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
				deferredImports.forEach(handler::register);
				handler.processGroupImports();
			}
		}
		finally {
			this.deferredImportSelectors = new ArrayList<>();
		}
	}
}

deferredImportSelectors集合中元素: 是解析启动类的@Import获取到ImportSelector类型的AutoConfigurationImportSelector时通过DeferredImportSelectorHandler#handle方法得到的。


2、DeferredImportSelectorGroupingHandler 

private class DeferredImportSelectorGroupingHandler {

	private final Map groupings = new LinkedHashMap<>();

	private final Map configurationClasses = new HashMap<>();

	public void register(DeferredImportSelectorHolder deferredImport) {
		Class group = deferredImport.getImportSelector().getImportGroup();
		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());
	}

	public void processGroupImports() {
		for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
			Predicate exclusionFilter = grouping.getCandidateFilter();
			grouping.getImports().forEach(entry -> {
				ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
				processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
							Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
							exclusionFilter, false);
			});
		}
	}

	private Group createGroup(@Nullable Class type) {
		Class effectiveType = (type != null ? type : DefaultDeferredImportSelectorGroup.class);
		return ParserStrategyUtils.instantiateClass(effectiveType, Group.class,
				ConfigurationClassParser.this.environment,
				ConfigurationClassParser.this.resourceLoader,
				ConfigurationClassParser.this.registry);
	}
}
grouping.getImports():获取自动装配的类。
entry:遍历每个自动装配的类

3、DeferredImportSelectorGrouping

private static class DeferredImportSelectorGrouping {

	private final DeferredImportSelector.Group group;

	private final List deferredImports = new ArrayList<>();

	DeferredImportSelectorGrouping(Group group) {
		this.group = group;
	}

	public void add(DeferredImportSelectorHolder deferredImport) {
		this.deferredImports.add(deferredImport);
	}
	
	public Iterable getImports() {
		for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
			this.group.process(deferredImport.getConfigurationClass().getMetadata(),
					deferredImport.getImportSelector());
		}
		return this.group.selectImports();
	}

	public Predicate getCandidateFilter() {
		Predicate mergedFilter = DEFAULT_EXCLUSION_FILTER;
		for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
			Predicate selectorFilter = deferredImport.getImportSelector().getExclusionFilter();
			if (selectorFilter != null) {
				mergedFilter = mergedFilter.or(selectorFilter);
			}
		}
		return mergedFilter;
	}
}

group.process:调用AutoConfigurationImportSelector的静态内部类AutoConfigurationGroup的方法AutoConfigurationGroup#process获取Spring.factories中涉及的类信息。

this.group.selectImports():对候选的自动装配类进行排序。首先按照全限定性名,其次再根据@AutoConfigureOrder、最后@AutoConfigureBefore @AutoConfigureAfter依次控制集合中候选类的顺序。

4、AutoConfigurationImportSelector

public class AutoConfigurationImportSelector implements DeferredImportSelector{
	
	protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {
		AnnotationAttributes attributes = getAttributes(annotationMetadata);

		// 通过spi机制加载spring.factories文件下的目标类
		List configurations = getCandidateConfigurations(annotationMetadata, attributes);//#1
		configurations = removeDuplicates(configurations);
		Set exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);

		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

	private List filter(List configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
		long startTime = System.nanoTime();
		String[] candidates = StringUtils.toStringArray(configurations);
		boolean[] skip = new boolean[candidates.length];
		boolean skipped = false;
		// AutoConfigurationImportFilter
		for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {//#2
			invokeAwareMethods(filter);
			boolean[] match = filter.match(candidates, autoConfigurationMetadata);//#3
			for (int i = 0; i < match.length; i++) {
				if (!match[i]) {
					skip[i] = true;
					candidates[i] = null;
					skipped = true;
				}
			}
		}
		if (!skipped) {
			return configurations;
		}
		List result = new ArrayList<>(candidates.length);
		for (int i = 0; i < candidates.length; i++) {
			if (!skip[i]) {
				result.add(candidates[i]);
			}
		}
		return new ArrayList<>(result);
	}

	private static class AutoConfigurationGroup implements DeferredImportSelector.Group{

		@Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {

			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);

			this.autoConfigurationEntries.add(autoConfigurationEntry);

			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}

		@Override
		public Iterable selectImports() {
			if (this.autoConfigurationEntries.isEmpty()) {
				return Collections.emptyList();
			}
			Set allExclusions = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
			Set processedConfigurations = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
					.collect(Collectors.toCollection(LinkedHashSet::new));
			processedConfigurations.removeAll(allExclusions);

			return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
					.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
					.collect(Collectors.toList());
		}

	}
}

步骤1:通过spi机制加载spring.factories文件下的目标类。

步骤2:在spring.factories文件中获取 AutoConfigurationImportFilter类型的过滤类。如下所示:

org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

 步骤3:遍历所有候选类。利用AutoConfigurationImportFilter三种不同类型判断候选类是否满足当前条件。

承接孪生文章

你可能感兴趣的:(spring,boot,spring,java)