Browse Source

AbstractApplicationContext resets local listeners to pre-refresh state

Closes gh-22325

(cherry picked from commit 0f73a69033)
pull/22521/head
Juergen Hoeller 6 years ago
parent
commit
ba330f1bcb
  1. 34
      spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java

34
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 */ /** Statically specified listeners */
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>(); private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/** ApplicationEvents published early */ /** Local listeners registered before refresh */
@Nullable
private Set<ApplicationListener<?>> earlyApplicationListeners;
/** ApplicationEvents published before the multicaster setup */
@Nullable @Nullable
private Set<ApplicationEvent> earlyApplicationEvents; private Set<ApplicationEvent> earlyApplicationEvents;
@ -485,7 +489,6 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
this.beanFactoryPostProcessors.add(postProcessor); this.beanFactoryPostProcessors.add(postProcessor);
} }
/** /**
* Return the list of BeanFactoryPostProcessors that will get applied * Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory. * 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. * active flag as well as performing any initialization of property sources.
*/ */
protected void prepareRefresh() { protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis(); this.startupDate = System.currentTimeMillis();
this.closed.set(false); this.closed.set(false);
this.active.set(true); this.active.set(true);
@ -588,13 +592,23 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
logger.info("Refreshing " + this); logger.info("Refreshing " + this);
} }
// Initialize any placeholder property sources in the context environment // Initialize any placeholder property sources in the context environment.
initPropertySources(); initPropertySources();
// Validate that all properties marked as required are resolvable // Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties // see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties(); 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, // Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available... // to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>(); this.earlyApplicationEvents = new LinkedHashSet<>();
@ -986,6 +1000,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @see #registerShutdownHook() * @see #registerShutdownHook()
*/ */
protected void doClose() { protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) { if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
logger.info("Closing " + this); logger.info("Closing " + this);
@ -1020,6 +1035,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
// Let subclasses do some final clean-up if they wish... // Let subclasses do some final clean-up if they wish...
onClose(); 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); this.active.set(false);
} }
} }
@ -1294,7 +1316,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
@Nullable @Nullable
protected MessageSource getInternalParentMessageSource() { protected MessageSource getInternalParentMessageSource() {
return (getParent() instanceof AbstractApplicationContext ? return (getParent() instanceof AbstractApplicationContext ?
((AbstractApplicationContext) getParent()).messageSource : getParent()); ((AbstractApplicationContext) getParent()).messageSource : getParent());
} }

Loading…
Cancel
Save