45
45
import org .springframework .context .ApplicationContext ;
46
46
import org .springframework .context .ApplicationEvent ;
47
47
import org .springframework .context .ApplicationListener ;
48
+ import org .springframework .context .ConfigurableApplicationContext ;
49
+ import org .springframework .context .SmartLifecycle ;
48
50
import org .springframework .context .event .ContextClosedEvent ;
49
51
import org .springframework .context .event .GenericApplicationListener ;
50
52
import org .springframework .core .Ordered ;
@@ -136,6 +138,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
136
138
*/
137
139
public static final String LOGGER_GROUPS_BEAN_NAME = "springBootLoggerGroups" ;
138
140
141
+ /**
142
+ * The name of the {@link Lifecycle} bean used to handle cleanup.
143
+ */
144
+ private static final String LOGGING_LIFECYCLE_BEAN_NAME = "springBootLoggingLifecycle" ;
145
+
139
146
private static final Map <String , List <String >> DEFAULT_GROUP_LOGGERS ;
140
147
static {
141
148
MultiValueMap <String , String > loggers = new LinkedMultiValueMap <>();
@@ -218,9 +225,8 @@ else if (event instanceof ApplicationEnvironmentPreparedEvent) {
218
225
else if (event instanceof ApplicationPreparedEvent ) {
219
226
onApplicationPreparedEvent ((ApplicationPreparedEvent ) event );
220
227
}
221
- else if (event instanceof ContextClosedEvent
222
- && ((ContextClosedEvent ) event ).getApplicationContext ().getParent () == null ) {
223
- onContextClosedEvent ();
228
+ else if (event instanceof ContextClosedEvent ) {
229
+ onContextClosedEvent ((ContextClosedEvent ) event );
224
230
}
225
231
else if (event instanceof ApplicationFailedEvent ) {
226
232
onApplicationFailedEvent ();
@@ -241,7 +247,8 @@ private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPrepare
241
247
}
242
248
243
249
private void onApplicationPreparedEvent (ApplicationPreparedEvent event ) {
244
- ConfigurableListableBeanFactory beanFactory = event .getApplicationContext ().getBeanFactory ();
250
+ ConfigurableApplicationContext applicationContext = event .getApplicationContext ();
251
+ ConfigurableListableBeanFactory beanFactory = applicationContext .getBeanFactory ();
245
252
if (!beanFactory .containsBean (LOGGING_SYSTEM_BEAN_NAME )) {
246
253
beanFactory .registerSingleton (LOGGING_SYSTEM_BEAN_NAME , this .loggingSystem );
247
254
}
@@ -251,20 +258,29 @@ private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
251
258
if (this .loggerGroups != null && !beanFactory .containsBean (LOGGER_GROUPS_BEAN_NAME )) {
252
259
beanFactory .registerSingleton (LOGGER_GROUPS_BEAN_NAME , this .loggerGroups );
253
260
}
261
+ if (!beanFactory .containsBean (LOGGING_LIFECYCLE_BEAN_NAME ) && applicationContext .getParent () == null ) {
262
+ beanFactory .registerSingleton (LOGGING_LIFECYCLE_BEAN_NAME , new Lifecycle ());
263
+ }
254
264
}
255
265
256
- private void onContextClosedEvent () {
257
- if (this .loggingSystem != null ) {
258
- this .loggingSystem .cleanUp ();
266
+ private void onContextClosedEvent (ContextClosedEvent event ) {
267
+ ApplicationContext applicationContext = event .getApplicationContext ();
268
+ if (applicationContext .getParent () != null || applicationContext .containsBean (LOGGING_LIFECYCLE_BEAN_NAME )) {
269
+ return ;
259
270
}
271
+ cleanupLoggingSystem ();
260
272
}
261
273
262
- private void onApplicationFailedEvent () {
274
+ void cleanupLoggingSystem () {
263
275
if (this .loggingSystem != null ) {
264
276
this .loggingSystem .cleanUp ();
265
277
}
266
278
}
267
279
280
+ private void onApplicationFailedEvent () {
281
+ cleanupLoggingSystem ();
282
+ }
283
+
268
284
/**
269
285
* Initialize the logging system according to preferences expressed through the
270
286
* {@link Environment} and the classpath.
@@ -438,4 +454,32 @@ public void setParseArgs(boolean parseArgs) {
438
454
this .parseArgs = parseArgs ;
439
455
}
440
456
457
+ private class Lifecycle implements SmartLifecycle {
458
+
459
+ private volatile boolean running ;
460
+
461
+ @ Override
462
+ public void start () {
463
+ this .running = true ;
464
+ }
465
+
466
+ @ Override
467
+ public void stop () {
468
+ this .running = false ;
469
+ cleanupLoggingSystem ();
470
+ }
471
+
472
+ @ Override
473
+ public boolean isRunning () {
474
+ return this .running ;
475
+ }
476
+
477
+ @ Override
478
+ public int getPhase () {
479
+ // Shutdown late and always after WebServerStartStopLifecycle
480
+ return Integer .MIN_VALUE + 1 ;
481
+ }
482
+
483
+ }
484
+
441
485
}
0 commit comments