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】