From ba330f1bcbe04157972b3b9556cb8c950c2041bf Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 7 Feb 2019 15:56:46 +0100 Subject: [PATCH] AbstractApplicationContext resets local listeners to pre-refresh state Closes gh-22325 (cherry picked from commit 0f73a69033e8ecc62af0a7a63167c09a2af495d7) --- .../support/AbstractApplicationContext.java | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java index 8101d16255..831b490f4f 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -211,7 +211,11 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader /** Statically specified listeners */ private final Set> applicationListeners = new LinkedHashSet<>(); - /** ApplicationEvents published early */ + /** Local listeners registered before refresh */ + @Nullable + private Set> earlyApplicationListeners; + + /** ApplicationEvents published before the multicaster setup */ @Nullable private Set earlyApplicationEvents; @@ -485,7 +489,6 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader this.beanFactoryPostProcessors.add(postProcessor); } - /** * Return the list of BeanFactoryPostProcessors that will get applied * to the internal BeanFactory. @@ -580,6 +583,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader * active flag as well as performing any initialization of property sources. */ protected void prepareRefresh() { + // Switch to active. this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); @@ -588,13 +592,23 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader logger.info("Refreshing " + this); } - // Initialize any placeholder property sources in the context environment + // Initialize any placeholder property sources in the context environment. initPropertySources(); - // Validate that all properties marked as required are resolvable + // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment().validateRequiredProperties(); + // Store pre-refresh ApplicationListeners... + if (this.earlyApplicationListeners == null) { + this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); + } + else { + // Reset local application listeners to pre-refresh state. + this.applicationListeners.clear(); + this.applicationListeners.addAll(this.earlyApplicationListeners); + } + // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); @@ -986,6 +1000,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader * @see #registerShutdownHook() */ protected void doClose() { + // Check whether an actual close attempt is necessary... if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isInfoEnabled()) { logger.info("Closing " + this); @@ -1020,6 +1035,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader // Let subclasses do some final clean-up if they wish... onClose(); + // Reset local application listeners to pre-refresh state. + if (this.earlyApplicationListeners != null) { + this.applicationListeners.clear(); + this.applicationListeners.addAll(this.earlyApplicationListeners); + } + + // Switch to inactive. this.active.set(false); } } @@ -1294,7 +1316,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader @Nullable protected MessageSource getInternalParentMessageSource() { return (getParent() instanceof AbstractApplicationContext ? - ((AbstractApplicationContext) getParent()).messageSource : getParent()); + ((AbstractApplicationContext) getParent()).messageSource : getParent()); }