二:springboot中bean的載入順序原理
阿新 • • 發佈:2020-12-24
技術標籤:java springboot
檢視一個關鍵的類
/* * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.autoconfigure; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.Assert; /** * Sort {@link EnableAutoConfiguration auto-configuration} classes into priority order by * reading {@link AutoConfigureOrder @AutoConfigureOrder}, * {@link AutoConfigureBefore @AutoConfigureBefore} and * {@link AutoConfigureAfter @AutoConfigureAfter} annotations (without loading classes). * * @author Phillip Webb */ class AutoConfigurationSorter { private final MetadataReaderFactory metadataReaderFactory; private final AutoConfigurationMetadata autoConfigurationMetadata; AutoConfigurationSorter(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata) { Assert.notNull(metadataReaderFactory, "MetadataReaderFactory must not be null"); this.metadataReaderFactory = metadataReaderFactory; this.autoConfigurationMetadata = autoConfigurationMetadata; } List<String> getInPriorityOrder(Collection<String> classNames) { AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory, this.autoConfigurationMetadata, classNames); List<String> orderedClassNames = new ArrayList<>(classNames); // Initially sort alphabetically Collections.sort(orderedClassNames); // Then sort by order orderedClassNames.sort((o1, o2) -> { int i1 = classes.get(o1).getOrder(); int i2 = classes.get(o2).getOrder(); return Integer.compare(i1, i2); }); // Then respect @AutoConfigureBefore @AutoConfigureAfter orderedClassNames = sortByAnnotation(classes, orderedClassNames); return orderedClassNames; } private List<String> sortByAnnotation(AutoConfigurationClasses classes, List<String> classNames) { List<String> toSort = new ArrayList<>(classNames); toSort.addAll(classes.getAllNames()); Set<String> sorted = new LinkedHashSet<>(); Set<String> processing = new LinkedHashSet<>(); while (!toSort.isEmpty()) { doSortByAfterAnnotation(classes, toSort, sorted, processing, null); } sorted.retainAll(classNames); return new ArrayList<>(sorted); } private void doSortByAfterAnnotation(AutoConfigurationClasses classes, List<String> toSort, Set<String> sorted, Set<String> processing, String current) { if (current == null) { current = toSort.remove(0); } processing.add(current); for (String after : classes.getClassesRequestedAfter(current)) { Assert.state(!processing.contains(after), "AutoConfigure cycle detected between " + current + " and " + after); if (!sorted.contains(after) && toSort.contains(after)) { doSortByAfterAnnotation(classes, toSort, sorted, processing, after); } } processing.remove(current); sorted.add(current); } private static class AutoConfigurationClasses { private final Map<String, AutoConfigurationClass> classes = new HashMap<>(); AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) { addToClasses(metadataReaderFactory, autoConfigurationMetadata, classNames, true); } Set<String> getAllNames() { return this.classes.keySet(); } private void addToClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames, boolean required) { for (String className : classNames) { if (!this.classes.containsKey(className)) { AutoConfigurationClass autoConfigurationClass = new AutoConfigurationClass(className, metadataReaderFactory, autoConfigurationMetadata); boolean available = autoConfigurationClass.isAvailable(); if (required || available) { this.classes.put(className, autoConfigurationClass); } if (available) { addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getBefore(), false); addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getAfter(), false); } } } } AutoConfigurationClass get(String className) { return this.classes.get(className); } Set<String> getClassesRequestedAfter(String className) { Set<String> classesRequestedAfter = new LinkedHashSet<>(get(className).getAfter()); this.classes.forEach((name, autoConfigurationClass) -> { if (autoConfigurationClass.getBefore().contains(className)) { classesRequestedAfter.add(name); } }); return classesRequestedAfter; } } private static class AutoConfigurationClass { private final String className; private final MetadataReaderFactory metadataReaderFactory; private final AutoConfigurationMetadata autoConfigurationMetadata; private volatile AnnotationMetadata annotationMetadata; private volatile Set<String> before; private volatile Set<String> after; AutoConfigurationClass(String className, MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata) { this.className = className; this.metadataReaderFactory = metadataReaderFactory; this.autoConfigurationMetadata = autoConfigurationMetadata; } boolean isAvailable() { try { if (!wasProcessed()) { getAnnotationMetadata(); } return true; } catch (Exception ex) { return false; } } Set<String> getBefore() { if (this.before == null) { this.before = (wasProcessed() ? this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureBefore", Collections.emptySet()) : getAnnotationValue(AutoConfigureBefore.class)); } return this.before; } Set<String> getAfter() { if (this.after == null) { this.after = (wasProcessed() ? this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureAfter", Collections.emptySet()) : getAnnotationValue(AutoConfigureAfter.class)); } return this.after; } private int getOrder() { if (wasProcessed()) { return this.autoConfigurationMetadata.getInteger(this.className, "AutoConfigureOrder", AutoConfigureOrder.DEFAULT_ORDER); } Map<String, Object> attributes = getAnnotationMetadata() .getAnnotationAttributes(AutoConfigureOrder.class.getName()); return (attributes != null) ? (Integer) attributes.get("value") : AutoConfigureOrder.DEFAULT_ORDER; } private boolean wasProcessed() { return (this.autoConfigurationMetadata != null && this.autoConfigurationMetadata.wasProcessed(this.className)); } private Set<String> getAnnotationValue(Class<?> annotation) { Map<String, Object> attributes = getAnnotationMetadata().getAnnotationAttributes(annotation.getName(), true); if (attributes == null) { return Collections.emptySet(); } Set<String> value = new LinkedHashSet<>(); Collections.addAll(value, (String[]) attributes.get("value")); Collections.addAll(value, (String[]) attributes.get("name")); return value; } private AnnotationMetadata getAnnotationMetadata() { if (this.annotationMetadata == null) { try { MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(this.className); this.annotationMetadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { throw new IllegalStateException("Unable to read meta-data for class " + this.className, ex); } } return this.annotationMetadata; } } }
看到其註釋資訊,3大註解按照優先權讀取。