diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java index 8cd7d81229a..817d1733598 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java @@ -45,15 +45,14 @@ public class RestartApplicationListener onApplicationStartingEvent((ApplicationStartingEvent) event); } if (event instanceof ApplicationPreparedEvent) { - Restarter.getInstance() - .prepare(((ApplicationPreparedEvent) event).getApplicationContext()); + onApplicationPreparedEvent((ApplicationPreparedEvent) event); } if (event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) { Restarter.getInstance().finish(); - if (event instanceof ApplicationFailedEvent) { - Restarter.getInstance().prepare(null); - } + } + if (event instanceof ApplicationFailedEvent) { + onApplicationFailedEvent((ApplicationFailedEvent) event); } } @@ -72,6 +71,14 @@ public class RestartApplicationListener } } + private void onApplicationPreparedEvent(ApplicationPreparedEvent event) { + Restarter.getInstance().prepare(event.getApplicationContext()); + } + + private void onApplicationFailedEvent(ApplicationFailedEvent event) { + Restarter.getInstance().remove(event.getApplicationContext()); + } + @Override public int getOrder() { return this.order; diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java index 1c94bc55061..681026c0325 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.BlockingDeque; import java.util.concurrent.Callable; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadFactory; import java.util.concurrent.locks.Lock; @@ -116,7 +117,7 @@ public class Restarter { private boolean finished = false; - private volatile ConfigurableApplicationContext rootContext; + private final List rootContexts = new CopyOnWriteArrayList(); /** * Internal constructor to create a new {@link Restarter} instance. @@ -314,9 +315,9 @@ public class Restarter { this.logger.debug("Stopping application"); this.stopLock.lock(); try { - if (this.rootContext != null) { - this.rootContext.close(); - this.rootContext = null; + for (ConfigurableApplicationContext context : this.rootContexts) { + context.close(); + this.rootContexts.remove(context); } cleanupCaches(); if (this.forceReferenceCleanup) { @@ -418,7 +419,13 @@ public class Restarter { if (applicationContext != null && applicationContext.getParent() != null) { return; } - this.rootContext = applicationContext; + this.rootContexts.add(applicationContext); + } + + void remove(ConfigurableApplicationContext applicationContext) { + if (applicationContext != null) { + this.rootContexts.remove(applicationContext); + } } private LeakSafeThread getLeakSafeThread() { diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java index 31acad0f0e2..34848adbc28 100644 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.devtools.restart; +import java.util.List; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,8 +66,8 @@ public class RestartApplicationListenerTests { assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args")) .isEqualTo(ARGS); assertThat(Restarter.getInstance().isFinished()).isTrue(); - assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext")) - .isNotNull(); + assertThat((List) ReflectionTestUtils.getField(Restarter.getInstance(), + "rootContexts")).isNotEmpty(); } @Test @@ -74,8 +76,8 @@ public class RestartApplicationListenerTests { assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args")) .isEqualTo(ARGS); assertThat(Restarter.getInstance().isFinished()).isTrue(); - assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext")) - .isNull(); + assertThat((List) ReflectionTestUtils.getField(Restarter.getInstance(), + "rootContexts")).isEmpty(); } @Test