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 文件。

SpringBoot启动过程中加载核心自动装配类的位置:其中包为spring-boot-autoconfigure。

文件为/META-INF/spring.factories 或者

/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration

1、DeferredImportSelectorHandler

private class DeferredImportSelectorHandler {

	@Nullable
	private List<DeferredImportSelectorHolder> 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<DeferredImportSelectorHolder> 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<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();
		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<String> 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<? extends Group> type) {
		Class<? extends Group> 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<DeferredImportSelectorHolder> deferredImports = new ArrayList<>();

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

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

	public Predicate<String> getCandidateFilter() {
		Predicate<String> mergedFilter = DEFAULT_EXCLUSION_FILTER;
		for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
			Predicate<String> 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<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//#1
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);

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

	...

	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<Entry> selectImports() {
			if (this.autoConfigurationEntries.isEmpty()) {
				return Collections.emptyList();
			}
			Set<String> allExclusions = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
			Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
					.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
					.collect(Collectors.toCollection(LinkedHashSet::new));
			processedConfigurations.removeAll(allExclusions);
			// 对自动装配的候选类排序处理:根据order字段属性排序、根据注解@AutoConfigureAfter、@AutoConfigureBefore
			return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
					.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
					.collect(Collectors.toList());
		}

		private List<String> sortAutoConfigurations(Set<String> configurations,
				AutoConfigurationMetadata autoConfigurationMetadata) {
			return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
                    //首先根据字母排序、其次根据Order排序、最后根据注解@AutoConfigureAfter、@AutoConfigureBefore 重新对候选类排序,改变其在集合中的顺序,从而影响候选类实例化顺序
					.getInPriorityOrder(configurations);
		}

	}
}

步骤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三种不同类型判断候选类是否满足当前条件。

承接孪生文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值