diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 0531c28bab..69f42ed0ea 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -296,6 +296,9 @@ public class SpringApplication { * @return a running {@link ApplicationContext} */ public ConfigurableApplicationContext run(String... args) { + if (this.registerShutdownHook) { + SpringApplication.shutdownHook.enableShutdowHookAddition(); + } long startTime = System.nanoTime(); DefaultBootstrapContext bootstrapContext = createBootstrapContext(); ConfigurableApplicationContext context = null; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationShutdownHook.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationShutdownHook.java index afa1ea89e9..da985828df 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationShutdownHook.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationShutdownHook.java @@ -62,12 +62,18 @@ class SpringApplicationShutdownHook implements Runnable { private final AtomicBoolean shutdownHookAdded = new AtomicBoolean(); + private volatile boolean shutdownHookAdditionEnabled = false; + private boolean inProgress; SpringApplicationShutdownHandlers getHandlers() { return this.handlers; } + void enableShutdowHookAddition() { + this.shutdownHookAdditionEnabled = true; + } + void registerApplicationContext(ConfigurableApplicationContext context) { addRuntimeShutdownHookIfNecessary(); synchronized (SpringApplicationShutdownHook.class) { @@ -78,7 +84,7 @@ class SpringApplicationShutdownHook implements Runnable { } private void addRuntimeShutdownHookIfNecessary() { - if (this.shutdownHookAdded.compareAndSet(false, true)) { + if (this.shutdownHookAdditionEnabled && this.shutdownHookAdded.compareAndSet(false, true)) { addRuntimeShutdownHook(); } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationShutdownHookTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationShutdownHookTests.java index c8cf5b1ffb..0ddb5b8c88 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationShutdownHookTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationShutdownHookTests.java @@ -51,6 +51,7 @@ class SpringApplicationShutdownHookTests { @Test void shutdownHookIsNotAddedUntilContextIsRegistered() { TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook(); + shutdownHook.enableShutdowHookAddition(); assertThat(shutdownHook.isRuntimeShutdownHookAdded()).isFalse(); ConfigurableApplicationContext context = new GenericApplicationContext(); shutdownHook.registerApplicationContext(context); @@ -60,12 +61,25 @@ class SpringApplicationShutdownHookTests { @Test void shutdownHookIsNotAddedUntilHandlerIsRegistered() { TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook(); + shutdownHook.enableShutdowHookAddition(); assertThat(shutdownHook.isRuntimeShutdownHookAdded()).isFalse(); shutdownHook.getHandlers().add(() -> { }); assertThat(shutdownHook.isRuntimeShutdownHookAdded()).isTrue(); } + @Test + void shutdownHookIsNotAddedUntilAdditionIsEnabled() { + TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook(); + shutdownHook.getHandlers().add(() -> { + }); + assertThat(shutdownHook.isRuntimeShutdownHookAdded()).isFalse(); + shutdownHook.enableShutdowHookAddition(); + shutdownHook.getHandlers().add(() -> { + }); + assertThat(shutdownHook.isRuntimeShutdownHookAdded()).isTrue(); + } + @Test void runClosesContextsBeforeRunningHandlerActions() { TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();