1. 程式人生 > 其它 >Springboot漫遊日誌(41)

Springboot漫遊日誌(41)

技術標籤:學習javaspring boot後端spring

Springboot漫遊日誌(41)

遺留:【Binder】【logback日誌】【載入properties或者yml】【解析環境變數key】【PathMatchingResourcePatternResolver】【AbstractBeanFactory】的【getBean(String name, Class requiredType)】方法

現在看:
【AnnotationTypeMapping】的構造方法

processAliases();
private void processAliases() {
List<Method> aliases = new ArrayList<>(); for (int i = 0; i < this.attributes.size(); i++) { aliases.clear(); aliases.add(this.attributes.get(i)); collectAliases(aliases); if (aliases.size() > 1) { processAliases(i, aliases); } } } private void collectAliases(List<
Method>
aliases) { AnnotationTypeMapping mapping = this; while (mapping != null) { int size = aliases.size(); for (int j = 0; j < size; j++) { List<Method> additional = mapping.aliasedBy.get(aliases.get(j)); if (additional != null) { aliases.addAll(additional); } } mapping =
mapping.source; } }

主要處理aliasedBy欄位
如果遍歷整個註解路徑,從第一個註解開始,解析到註解的註解。

在這裡插入圖片描述

這裡的註解是SpringBootApplication,所以aliases的size都是0,進入不了if。

看下一個方法。

private void addConventionMappings() {
	if (this.distance == 0) {
		return;
	}
	AttributeMethods rootAttributes = this.root.getAttributes();
	int[] mappings = this.conventionMappings;
	for (int i = 0; i < mappings.length; i++) {
		String name = this.attributes.get(i).getName();
		MirrorSet mirrors = getMirrorSets().getAssigned(i);
		int mapped = rootAttributes.indexOf(name);
		if (!MergedAnnotation.VALUE.equals(name) && mapped != -1) {
			mappings[i] = mapped;
			if (mirrors != null) {
				for (int j = 0; j < mirrors.size(); j++) {
					mappings[mirrors.getAttributeIndex(j)] = mapped;
				}
			}
		}
	}
}

distance 的值是0,也不用往下看了。

private void addConventionAnnotationValues() {
	for (int i = 0; i < this.attributes.size(); i++) {
		Method attribute = this.attributes.get(i);
		boolean isValueAttribute = MergedAnnotation.VALUE.equals(attribute.getName());
		AnnotationTypeMapping mapping = this;
		while (mapping != null && mapping.distance > 0) {
			int mapped = mapping.getAttributes().indexOf(attribute.getName());
			if (mapped != -1 && isBetterConventionAnnotationValue(i, isValueAttribute, mapping)) {
				this.annotationValueMappings[i] = mapped;
				this.annotationValueSource[i] = mapping;
			}
			mapping = mapping.source;
		}
	}
}

distance 是0,也不用往下看了。

看最後一個屬性。

private boolean computeSynthesizableFlag() {
	// Uses @AliasFor for local aliases?
	for (int index : this.aliasMappings) {
		if (index != -1) {
			return true;
		}
	}

	// Uses @AliasFor for attribute overrides in meta-annotations?
	if (!this.aliasedBy.isEmpty()) {
		return true;
	}

	// Uses convention-based attribute overrides in meta-annotations?
	for (int index : this.conventionMappings) {
		if (index != -1) {
			return true;
		}
	}

	// Has nested annotations or arrays of annotations that are synthesizable?
	if (getAttributes().hasNestedAnnotation()) {
		AttributeMethods attributeMethods = getAttributes();
		for (int i = 0; i < attributeMethods.size(); i++) {
			Method method = attributeMethods.get(i);
			Class<?> type = method.getReturnType();
			if (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation())) {
				Class<? extends Annotation> annotationType =
						(Class<? extends Annotation>) (type.isAnnotation() ? type : type.getComponentType());
				AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
				if (mapping.isSynthesizable()) {
					return true;
				}
			}
		}
	}

	return false;
}

aliasedBy不是空的,返回true。

回到【AnnotationTypeMappings】的方法【addAllMappings】

private void addAllMappings(Class<? extends Annotation> annotationType) {
	Deque<AnnotationTypeMapping> queue = new ArrayDeque<>();
	addIfPossible(queue, null, annotationType, null);
	while (!queue.isEmpty()) {
		AnnotationTypeMapping mapping = queue.removeFirst();
		this.mappings.add(mapping);
		addMetaAnnotationsToQueue(queue, mapping);
	}
}

進入while迴圈。
把剛剛例項化的mapping放入到mappings

private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source) {
	Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType(), false);
	for (Annotation metaAnnotation : metaAnnotations) {
		if (!isMappable(source, metaAnnotation)) {
			continue;
		}
		Annotation[] repeatedAnnotations = this.repeatableContainers.findRepeatedAnnotations(metaAnnotation);
		if (repeatedAnnotations != null) {
			for (Annotation repeatedAnnotation : repeatedAnnotations) {
				if (!isMappable(source, repeatedAnnotation)) {
					continue;
				}
				addIfPossible(queue, source, repeatedAnnotation);
			}
		}
		else {
			addIfPossible(queue, source, metaAnnotation);
		}
	}
}

把SpringBootApplication註解的所有元註解都加入到佇列中。

private void addIfPossible(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source, Annotation ann) {
	addIfPossible(queue, source, ann.annotationType(), ann);
}

private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable AnnotationTypeMapping source,
		Class<? extends Annotation> annotationType, @Nullable Annotation ann) {

	try {
		queue.addLast(new AnnotationTypeMapping(source, annotationType, ann));
	}
	catch (Exception ex) {
		AnnotationUtils.rethrowAnnotationConfigurationException(ex);
		if (failureLogger.isEnabled()) {
			failureLogger.log("Failed to introspect meta-annotation " + annotationType.getName(),
					(source != null ? source.getAnnotationType() : null), ex);
		}
	}
}

同樣的操作再走一遍,但是註解類不再是SpringBootApplication。
直到把所有的註解都例項化成【AnnotationTypeMapping】
並把他們加入到【mappings】

this.mappings.forEach(AnnotationTypeMapping::afterAllMappingsSet);

然後遍歷這個集合,對每一個【AnnotationTypeMapping】執行【afterAllMappingsSet】方法。

/**
 * Method called after all mappings have been set. At this point no further
 * lookups from child mappings will occur.
 */
void afterAllMappingsSet() {
	validateAllAliasesClaimed();
	for (int i = 0; i < this.mirrorSets.size(); i++) {
		validateMirrorSet(this.mirrorSets.get(i));
	}
	this.claimedAliases.clear();
}

private void validateAllAliasesClaimed() {
	for (int i = 0; i < this.attributes.size(); i++) {
		Method attribute = this.attributes.get(i);
		AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, AliasFor.class);
		if (aliasFor != null && !this.claimedAliases.contains(attribute)) {
			Method target = resolveAliasTarget(attribute, aliasFor);
			throw new AnnotationConfigurationException(String.format(
					"@AliasFor declaration on %s declares an alias for %s which is not meta-present.",
					AttributeMethods.describe(attribute), AttributeMethods.describe(target)));
		}
	}
}

private void validateMirrorSet(MirrorSet mirrorSet) {
	Method firstAttribute = mirrorSet.get(0);
	Object firstDefaultValue = firstAttribute.getDefaultValue();
	for (int i = 1; i <= mirrorSet.size() - 1; i++) {
		Method mirrorAttribute = mirrorSet.get(i);
		Object mirrorDefaultValue = mirrorAttribute.getDefaultValue();
		if (firstDefaultValue == null || mirrorDefaultValue == null) {
			throw new AnnotationConfigurationException(String.format(
					"Misconfigured aliases: %s and %s must declare default values.",
					AttributeMethods.describe(firstAttribute), AttributeMethods.describe(mirrorAttribute)));
		}
		if (!ObjectUtils.nullSafeEquals(firstDefaultValue, mirrorDefaultValue)) {
			throw new AnnotationConfigurationException(String.format(
					"Misconfigured aliases: %s and %s must declare the same default value.",
					AttributeMethods.describe(firstAttribute), AttributeMethods.describe(mirrorAttribute)));
		}
	}
}

全部都是校驗檢查,不對就丟擲異常。
啥異常先不看了。

返回到【IsPresent】的【doWithAnnotations】方法。

@Override
@Nullable
public Boolean doWithAnnotations(Object requiredType, int aggregateIndex,
		@Nullable Object source, Annotation[] annotations) {

	for (Annotation annotation : annotations) {
		if (annotation != null) {
			Class<? extends Annotation> type = annotation.annotationType();
			if (type != null && !this.annotationFilter.matches(type)) {
				if (type == requiredType || type.getName().equals(requiredType)) {
					return Boolean.TRUE;
				}
				Annotation[] repeatedAnnotations =
						this.repeatableContainers.findRepeatedAnnotations(annotation);
				if (repeatedAnnotations != null) {
					Boolean result = doWithAnnotations(
							requiredType, aggregateIndex, source, repeatedAnnotations);
					if (result != null) {
						return result;
					}
				}
				if (!this.directOnly) {
					AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(type);
					for (int i = 0; i < mappings.size(); i++) {
						AnnotationTypeMapping mapping = mappings.get(i);
						if (isMappingForType(mapping, this.annotationFilter, requiredType)) {
							return Boolean.TRUE;
						}
					}
				}
			}
		}
	}
	return null;
}

剛剛跑完這一句。

AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(type);
private static boolean isMappingForType(AnnotationTypeMapping mapping,
			AnnotationFilter annotationFilter, @Nullable Object requiredType) {
	Class<? extends Annotation> actualType = mapping.getAnnotationType();
	return (!annotationFilter.matches(actualType) &&
			(requiredType == null || actualType == requiredType || actualType.getName().equals(requiredType)));
}

判斷給定的註解是否包含在元註解裡面,在就返回true。
給定的四個註解是。

private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
	candidateIndicators.add(Component.class.getName());
	candidateIndicators.add(ComponentScan.class.getName());
	candidateIndicators.add(Import.class.getName());
	candidateIndicators.add(ImportResource.class.getName());
}

很顯然,是有的,結果為true。
回到【ConfigurationClassUtils】的【isConfigurationCandidate】方法。
結果返回true。

返回【ConditionEvaluator】的【shouldSkip】方法。

/**
 * Determine if an item should be skipped based on {@code @Conditional} annotations.
 * @param metadata the meta data
 * @param phase the phase of the call
 * @return if the item should be skipped
 */
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
	if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
		return false;
	}

	if (phase == null) {
		if (metadata instanceof AnnotationMetadata &&
				ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
			return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
		}
		return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
	}

	List<Condition> conditions = new ArrayList<>();
	for (String[] conditionClasses : getConditionClasses(metadata)) {
		for (String conditionClass : conditionClasses) {
			Condition condition = getCondition(conditionClass, this.context.getClassLoader());
			conditions.add(condition);
		}
	}

	AnnotationAwareOrderComparator.sort(conditions);

	for (Condition condition : conditions) {
		ConfigurationPhase requiredPhase = null;
		if (condition instanceof ConfigurationCondition) {
			requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
		}
		if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
			return true;
		}
	}

	return false;
}

走到第三個if中
再次呼叫這個方法,不過第二個引數變成了【ConfigurationPhase.PARSE_CONFIGURATION】
所以第二次呼叫,直接跳過了前3個if。


遺留:【Binder】【logback日誌】【載入properties或者yml】【解析環境變數key】【PathMatchingResourcePatternResolver】【AbstractBeanFactory】的【getBean(String name, Class requiredType)】方法

現在看:
【ConditionEvaluator】的【shouldSkip】方法。

下次看:
【ConditionEvaluator】的【shouldSkip】方法。
跳過前面3個if。
引數是:
metadata【StandardAnnotationMetadata】
phase【ConfigurationPhase.PARSE_CONFIGURATION】