commit
7216d2b031
|
@ -20,11 +20,13 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.Comparator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.core.type.classreading.MetadataReader;
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
@ -53,12 +55,14 @@ class AutoConfigurationSorter {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getInPriorityOrder(Collection<String> classNames) {
|
List<String> getInPriorityOrder(Collection<String> classNames) {
|
||||||
AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
|
|
||||||
this.autoConfigurationMetadata, classNames);
|
|
||||||
List<String> orderedClassNames = new ArrayList<>(classNames);
|
|
||||||
// Initially sort alphabetically
|
// Initially sort alphabetically
|
||||||
Collections.sort(orderedClassNames);
|
List<String> alphabeticallyOrderedClassNames = new ArrayList<>(classNames);
|
||||||
|
Collections.sort(alphabeticallyOrderedClassNames);
|
||||||
// Then sort by order
|
// Then sort by order
|
||||||
|
AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
|
||||||
|
this.autoConfigurationMetadata, alphabeticallyOrderedClassNames);
|
||||||
|
List<String> orderedClassNames = new ArrayList<>(classNames);
|
||||||
|
Collections.sort(orderedClassNames);
|
||||||
orderedClassNames.sort((o1, o2) -> {
|
orderedClassNames.sort((o1, o2) -> {
|
||||||
int i1 = classes.get(o1).getOrder();
|
int i1 = classes.get(o1).getOrder();
|
||||||
int i2 = classes.get(o2).getOrder();
|
int i2 = classes.get(o2).getOrder();
|
||||||
|
@ -87,7 +91,9 @@ class AutoConfigurationSorter {
|
||||||
current = toSort.remove(0);
|
current = toSort.remove(0);
|
||||||
}
|
}
|
||||||
processing.add(current);
|
processing.add(current);
|
||||||
for (String after : classes.getClassesRequestedAfter(current)) {
|
Set<String> afters = new TreeSet<>(Comparator.comparing(toSort::indexOf));
|
||||||
|
afters.addAll(classes.getClassesRequestedAfter(current));
|
||||||
|
for (String after : afters) {
|
||||||
checkForCycles(processing, current, after);
|
checkForCycles(processing, current, after);
|
||||||
if (!sorted.contains(after) && toSort.contains(after)) {
|
if (!sorted.contains(after) && toSort.contains(after)) {
|
||||||
doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
|
doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
|
||||||
|
@ -104,7 +110,7 @@ class AutoConfigurationSorter {
|
||||||
|
|
||||||
private static class AutoConfigurationClasses {
|
private static class AutoConfigurationClasses {
|
||||||
|
|
||||||
private final Map<String, AutoConfigurationClass> classes = new HashMap<>();
|
private final Map<String, AutoConfigurationClass> classes = new LinkedHashMap<>();
|
||||||
|
|
||||||
AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory,
|
AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory,
|
||||||
AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
|
AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ import static org.mockito.Mockito.mock;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
|
* @author Alexandre Baron
|
||||||
*/
|
*/
|
||||||
class AutoConfigurationSorterTests {
|
class AutoConfigurationSorterTests {
|
||||||
|
|
||||||
|
@ -206,6 +207,17 @@ class AutoConfigurationSorterTests {
|
||||||
.withMessageContaining("AutoConfigure cycle detected");
|
.withMessageContaining("AutoConfigure cycle detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-38904
|
||||||
|
void byBeforeAnnotationThenOrderAnnotation() {
|
||||||
|
String oa = OrderAutoConfigureA.class.getName();
|
||||||
|
String oa1 = OrderAutoConfigureASeedR1.class.getName();
|
||||||
|
String oa2 = OrderAutoConfigureASeedY2.class.getName();
|
||||||
|
String oa3 = OrderAutoConfigureASeedA3.class.getName();
|
||||||
|
String oa4 = OrderAutoConfigureAutoConfigureASeedG4.class.getName();
|
||||||
|
List<String> actual = this.sorter.getInPriorityOrder(Arrays.asList(oa4, oa3, oa2, oa1, oa));
|
||||||
|
assertThat(actual).containsExactly(oa1, oa2, oa3, oa4, oa);
|
||||||
|
}
|
||||||
|
|
||||||
private AutoConfigurationMetadata getAutoConfigurationMetadata(String... classNames) throws Exception {
|
private AutoConfigurationMetadata getAutoConfigurationMetadata(String... classNames) throws Exception {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
|
@ -348,6 +360,36 @@ class AutoConfigurationSorterTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class OrderAutoConfigureA {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use seeds in auto-configuration class names to mislead the sort by names done in
|
||||||
|
// AutoConfigurationSorter class.
|
||||||
|
@AutoConfigureBefore(OrderAutoConfigureA.class)
|
||||||
|
@AutoConfigureOrder(1)
|
||||||
|
static class OrderAutoConfigureASeedR1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoConfigureBefore(OrderAutoConfigureA.class)
|
||||||
|
@AutoConfigureOrder(2)
|
||||||
|
static class OrderAutoConfigureASeedY2 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoConfigureBefore(OrderAutoConfigureA.class)
|
||||||
|
@AutoConfigureOrder(3)
|
||||||
|
static class OrderAutoConfigureASeedA3 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoConfigureBefore(OrderAutoConfigureA.class)
|
||||||
|
@AutoConfigureOrder(4)
|
||||||
|
static class OrderAutoConfigureAutoConfigureASeedG4 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static class SkipCycleMetadataReaderFactory extends CachingMetadataReaderFactory {
|
static class SkipCycleMetadataReaderFactory extends CachingMetadataReaderFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue