diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java index ab691e235e..40e4ef635f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -63,8 +63,8 @@ public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoad protected List getAutoConfigurations() { if (this.autoConfigurations == null) { - this.autoConfigurations = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader) - .getCandidates(); + ImportCandidates importCandidates = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader); + this.autoConfigurations = importCandidates.getCandidates(); } return this.autoConfigurations; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java index e9e9f16429..025b1aedf8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java @@ -76,6 +76,8 @@ import org.springframework.util.StringUtils; public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { + static final int ORDER = Ordered.LOWEST_PRECEDENCE - 1; + private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry(); private static final String[] NO_IMPORTS = {}; @@ -92,7 +94,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, private ResourceLoader resourceLoader; - private ConfigurationClassFilter configurationClassFilter; + private volatile ConfigurationClassFilter configurationClassFilter; @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { @@ -177,8 +179,8 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, * @return a list of candidate configurations */ protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { - List configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()) - .getCandidates(); + ImportCandidates importCandidates = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()); + List configurations = importCandidates.getCandidates(); Assert.notEmpty(configurations, "No auto configuration classes found in " + "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you " @@ -254,14 +256,16 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, } private ConfigurationClassFilter getConfigurationClassFilter() { - if (this.configurationClassFilter == null) { + ConfigurationClassFilter configurationClassFilter = this.configurationClassFilter; + if (configurationClassFilter == null) { List filters = getAutoConfigurationImportFilters(); for (AutoConfigurationImportFilter filter : filters) { invokeAwareMethods(filter); } - this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters); + configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters); + this.configurationClassFilter = configurationClassFilter; } - return this.configurationClassFilter; + return configurationClassFilter; } protected final List removeDuplicates(List list) { @@ -344,7 +348,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @Override public int getOrder() { - return Ordered.LOWEST_PRECEDENCE - 1; + return ORDER; } private static class ConfigurationClassFilter { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurations.java index 2063a69fb2..f5654ea4db 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurations.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -39,7 +39,7 @@ public class AutoConfigurations extends Configurations implements Ordered { private static final AutoConfigurationSorter SORTER = new AutoConfigurationSorter(new SimpleMetadataReaderFactory(), null); - private static final Ordered ORDER = new AutoConfigurationImportSelector(); + private static final int ORDER = AutoConfigurationImportSelector.ORDER; protected AutoConfigurations(Collection> classes) { super(classes); @@ -56,7 +56,7 @@ public class AutoConfigurations extends Configurations implements Ordered { @Override public int getOrder() { - return ORDER.getOrder(); + return ORDER; } @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java index b9bb92d466..93a00ba89c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -97,19 +97,19 @@ class AutoConfigurationSorterTests { @Test void byOrderAnnotation() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(LOWEST, HIGHEST, DEFAULT)); + List actual = getInPriorityOrder(LOWEST, HIGHEST, DEFAULT); assertThat(actual).containsExactly(HIGHEST, DEFAULT, LOWEST); } @Test void byAutoConfigureAfter() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A, B, C)); + List actual = getInPriorityOrder(A, B, C); assertThat(actual).containsExactly(C, B, A); } @Test void byAutoConfigureAfterAliasFor() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A3, B2, C)); + List actual = getInPriorityOrder(A3, B2, C); assertThat(actual).containsExactly(C, B2, A3); } @@ -118,19 +118,19 @@ class AutoConfigurationSorterTests { MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(); this.autoConfigurationMetadata = getAutoConfigurationMetadata(A3, B2, C); this.sorter = new AutoConfigurationSorter(readerFactory, this.autoConfigurationMetadata); - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A3, B2, C)); + List actual = getInPriorityOrder(A3, B2, C); assertThat(actual).containsExactly(C, B2, A3); } @Test void byAutoConfigureBefore() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(X, Y, Z)); + List actual = getInPriorityOrder(X, Y, Z); assertThat(actual).containsExactly(Z, Y, X); } @Test void byAutoConfigureBeforeAliasFor() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(X, Y2, Z2)); + List actual = getInPriorityOrder(X, Y2, Z2); assertThat(actual).containsExactly(Z2, Y2, X); } @@ -139,44 +139,44 @@ class AutoConfigurationSorterTests { MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(); this.autoConfigurationMetadata = getAutoConfigurationMetadata(X, Y2, Z2); this.sorter = new AutoConfigurationSorter(readerFactory, this.autoConfigurationMetadata); - List actual = this.sorter.getInPriorityOrder(Arrays.asList(X, Y2, Z2)); + List actual = getInPriorityOrder(X, Y2, Z2); assertThat(actual).containsExactly(Z2, Y2, X); } @Test void byAutoConfigureAfterDoubles() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A, B, C, E)); + List actual = getInPriorityOrder(A, B, C, E); assertThat(actual).containsExactly(C, E, B, A); } @Test void byAutoConfigureMixedBeforeAndAfter() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A, B, C, W, X)); + List actual = getInPriorityOrder(A, B, C, W, X); assertThat(actual).containsExactly(C, W, B, A, X); } @Test void byAutoConfigureMixedBeforeAndAfterWithClassNames() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A2, B, C, W2, X)); + List actual = getInPriorityOrder(A2, B, C, W2, X); assertThat(actual).containsExactly(C, W2, B, A2, X); } @Test void byAutoConfigureMixedBeforeAndAfterWithDifferentInputOrder() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(W, X, A, B, C)); + List actual = getInPriorityOrder(W, X, A, B, C); assertThat(actual).containsExactly(C, W, B, A, X); } @Test void byAutoConfigureAfterWithMissing() { - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A, B)); + List actual = getInPriorityOrder(A, B); assertThat(actual).containsExactly(B, A); } @Test void byAutoConfigureAfterWithCycle() { this.sorter = new AutoConfigurationSorter(new CachingMetadataReaderFactory(), this.autoConfigurationMetadata); - assertThatIllegalStateException().isThrownBy(() -> this.sorter.getInPriorityOrder(Arrays.asList(A, B, C, D))) + assertThatIllegalStateException().isThrownBy(() -> getInPriorityOrder(A, B, C, D)) .withMessageContaining("AutoConfigure cycle detected"); } @@ -185,7 +185,7 @@ class AutoConfigurationSorterTests { MetadataReaderFactory readerFactory = new SkipCycleMetadataReaderFactory(); this.autoConfigurationMetadata = getAutoConfigurationMetadata(A2, B, C, W2, X); this.sorter = new AutoConfigurationSorter(readerFactory, this.autoConfigurationMetadata); - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A2, B, C, W2, X)); + List actual = getInPriorityOrder(A2, B, C, W2, X); assertThat(actual).containsExactly(C, W2, B, A2, X); } @@ -194,7 +194,7 @@ class AutoConfigurationSorterTests { MetadataReaderFactory readerFactory = new SkipCycleMetadataReaderFactory(); this.autoConfigurationMetadata = getAutoConfigurationMetadata(A, B, E); this.sorter = new AutoConfigurationSorter(readerFactory, this.autoConfigurationMetadata); - List actual = this.sorter.getInPriorityOrder(Arrays.asList(A, E)); + List actual = getInPriorityOrder(A, E); assertThat(actual).containsExactly(E, A); } @@ -203,7 +203,7 @@ class AutoConfigurationSorterTests { MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(); this.autoConfigurationMetadata = getAutoConfigurationMetadata(A, B, D); this.sorter = new AutoConfigurationSorter(readerFactory, this.autoConfigurationMetadata); - assertThatIllegalStateException().isThrownBy(() -> this.sorter.getInPriorityOrder(Arrays.asList(D, B))) + assertThatIllegalStateException().isThrownBy(() -> getInPriorityOrder(D, B)) .withMessageContaining("AutoConfigure cycle detected"); } @@ -214,10 +214,14 @@ class AutoConfigurationSorterTests { String oa2 = OrderAutoConfigureASeedY2.class.getName(); String oa3 = OrderAutoConfigureASeedA3.class.getName(); String oa4 = OrderAutoConfigureAutoConfigureASeedG4.class.getName(); - List actual = this.sorter.getInPriorityOrder(Arrays.asList(oa4, oa3, oa2, oa1, oa)); + List actual = getInPriorityOrder(oa4, oa3, oa2, oa1, oa); assertThat(actual).containsExactly(oa1, oa2, oa3, oa4, oa); } + private List getInPriorityOrder(String... classNames) { + return this.sorter.getInPriorityOrder(Arrays.asList(classNames)); + } + private AutoConfigurationMetadata getAutoConfigurationMetadata(String... classNames) throws Exception { Properties properties = new Properties(); for (String className : classNames) {