diff --git a/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureRules.java b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureRules.java
index e45c24ee6ba..7630e045a09 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureRules.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureRules.java
@@ -130,7 +130,12 @@ final class ArchitectureRules {
}
private static ArchRule allPackagesShouldBeFreeOfTangles() {
- return SlicesRuleDefinition.slices().matching("(**)").should().beFreeOfCycles();
+ return SlicesRuleDefinition.slices()
+ .matching("(**)")
+ .should()
+ .beFreeOfCycles()
+ .ignoreDependency("org.springframework.boot.env.EnvironmentPostProcessor",
+ "org.springframework.boot.SpringApplication");
}
private static ArchRule allBeanPostProcessorBeanMethodsShouldBeStaticAndNotCausePrematureInitialization() {
diff --git a/core/spring-boot/src/main/java/org/springframework/boot/env/EnvironmentPostProcessor.java b/core/spring-boot/src/main/java/org/springframework/boot/env/EnvironmentPostProcessor.java
new file mode 100644
index 00000000000..08ccbaf1d7a
--- /dev/null
+++ b/core/spring-boot/src/main/java/org/springframework/boot/env/EnvironmentPostProcessor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-present 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.env;
+
+import org.springframework.boot.bootstrap.BootstrapContext;
+import org.springframework.boot.bootstrap.BootstrapRegistry;
+import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
+import org.springframework.boot.logging.DeferredLogFactory;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
+
+/**
+ * Allows for customization of the application's {@link Environment} prior to the
+ * application context being refreshed.
+ *
+ * EnvironmentPostProcessor implementations have to be registered in
+ * {@code META-INF/spring.factories}, using the fully qualified name of this class as the
+ * key. Implementations may implement the {@link org.springframework.core.Ordered Ordered}
+ * interface or use an {@link org.springframework.core.annotation.Order @Order} annotation
+ * if they wish to be invoked in specific order.
+ *
+ * Since Spring Boot 2.4, {@code EnvironmentPostProcessor} implementations may optionally
+ * take the following constructor parameters:
+ *
+ *
{@link DeferredLogFactory} - A factory that can be used to create loggers with
+ * output deferred until the application has been fully prepared (allowing the environment
+ * itself to configure logging levels).
+ *
{@link ConfigurableBootstrapContext} - A bootstrap context that can be used to
+ * store objects that may be expensive to create, or need to be shared
+ * ({@link BootstrapContext} or {@link BootstrapRegistry} may also be used).
+ *
+ *
+ * @author Andy Wilkinson
+ * @author Stephane Nicoll
+ * @since 1.3.0
+ * @deprecated since 4.0.0 for removal in 4.2.0 in favor of
+ * {@link org.springframework.boot.EnvironmentPostProcessor}
+ */
+@FunctionalInterface
+@Deprecated(since = "4.0.0", forRemoval = true)
+public interface EnvironmentPostProcessor {
+
+ /**
+ * Post-process the given {@code environment}.
+ * @param environment the environment to post-process
+ * @param application the application to which the environment belongs
+ */
+ void postProcessEnvironment(ConfigurableEnvironment environment,
+ org.springframework.boot.SpringApplication application);
+
+}
diff --git a/core/spring-boot/src/main/java/org/springframework/boot/support/SpringFactoriesEnvironmentPostProcessorsFactory.java b/core/spring-boot/src/main/java/org/springframework/boot/support/SpringFactoriesEnvironmentPostProcessorsFactory.java
index f0bc7310540..ba92a12b5fb 100644
--- a/core/spring-boot/src/main/java/org/springframework/boot/support/SpringFactoriesEnvironmentPostProcessorsFactory.java
+++ b/core/spring-boot/src/main/java/org/springframework/boot/support/SpringFactoriesEnvironmentPostProcessorsFactory.java
@@ -16,13 +16,18 @@
package org.springframework.boot.support;
+import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import org.springframework.boot.EnvironmentPostProcessor;
+import org.springframework.boot.SpringApplication;
import org.springframework.boot.bootstrap.BootstrapContext;
import org.springframework.boot.bootstrap.BootstrapRegistry;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.boot.logging.DeferredLogFactory;
+import org.springframework.core.annotation.AnnotationAwareOrderComparator;
+import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver;
@@ -46,7 +51,34 @@ class SpringFactoriesEnvironmentPostProcessorsFactory implements EnvironmentPost
argumentResolver = argumentResolver.and(ConfigurableBootstrapContext.class, bootstrapContext);
argumentResolver = argumentResolver.and(BootstrapContext.class, bootstrapContext);
argumentResolver = argumentResolver.and(BootstrapRegistry.class, bootstrapContext);
- return this.loader.load(EnvironmentPostProcessor.class, argumentResolver);
+ List