Fix some sloppy code in context hierarchy support
* The SpringApplicationBuilder was registering the parent context initializer twice (not really a problem, but confusing if you are debugging). * ParentContextApplicationContextInitializer itself should have been checking that the current context is not the parent * The EventPublishingRunListener as a result needs to call setApplicationContext on any listeners that are AplicationContextAware * ParentContextCloserApplicationListener can ensure that there is only one of its kind per application context by implementing hashCode and equals Fixes gh-1142
This commit is contained in:
parent
d2b88d741c
commit
999748bdab
|
|
@ -53,8 +53,10 @@ public class ParentContextApplicationContextInitializer implements
|
|||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
applicationContext.setParent(this.parent);
|
||||
applicationContext.addApplicationListener(EventPublisher.INSTANCE);
|
||||
if (applicationContext != this.parent) {
|
||||
applicationContext.setParent(this.parent);
|
||||
applicationContext.addApplicationListener(EventPublisher.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EventPublisher implements
|
||||
|
|
@ -70,7 +72,8 @@ public class ParentContextApplicationContextInitializer implements
|
|||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
ApplicationContext context = event.getApplicationContext();
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
if (context instanceof ConfigurableApplicationContext
|
||||
&& context == event.getSource()) {
|
||||
context.publishEvent(new ParentContextAvailableEvent(
|
||||
(ConfigurableApplicationContext) context));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ package org.springframework.boot.builder;
|
|||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.builder.ParentContextApplicationContextInitializer.ParentContextAvailableEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
|
|
@ -33,11 +36,21 @@ import org.springframework.core.Ordered;
|
|||
* @author Eric Bottard
|
||||
*/
|
||||
public class ParentContextCloserApplicationListener implements
|
||||
ApplicationListener<ParentContextAvailableEvent>, Ordered {
|
||||
ApplicationListener<ParentContextAvailableEvent>, ApplicationContextAware,
|
||||
Ordered {
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE - 10;
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE - 10;
|
||||
return this.order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -46,10 +59,12 @@ public class ParentContextCloserApplicationListener implements
|
|||
}
|
||||
|
||||
private void maybeInstallListenerInParent(ConfigurableApplicationContext child) {
|
||||
if (child.getParent() instanceof ConfigurableApplicationContext) {
|
||||
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) child
|
||||
.getParent();
|
||||
parent.addApplicationListener(createContextCloserListener(child));
|
||||
if (child == this.context) {
|
||||
if (child.getParent() instanceof ConfigurableApplicationContext) {
|
||||
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) child
|
||||
.getParent();
|
||||
parent.addApplicationListener(createContextCloserListener(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +97,35 @@ public class ParentContextCloserApplicationListener implements
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime
|
||||
* result
|
||||
+ ((this.childContext.get() == null) ? 0 : this.childContext.get()
|
||||
.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ContextCloserListener other = (ContextCloserListener) obj;
|
||||
if (this.childContext.get() == null) {
|
||||
if (other.childContext.get() != null)
|
||||
return false;
|
||||
}
|
||||
else if (!this.childContext.get().equals(other.childContext.get()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@ public class SpringApplicationBuilder {
|
|||
this.parent = new SpringApplicationBuilder();
|
||||
this.parent.context = parent;
|
||||
this.parent.running.set(true);
|
||||
initializers(new ParentContextApplicationContextInitializer(parent));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.context.event;
|
|||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringApplicationRunListener;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ApplicationEventMulticaster;
|
||||
|
|
@ -78,6 +79,9 @@ public class EventPublishingRunListener implements SpringApplicationRunListener
|
|||
@Override
|
||||
public void contextLoaded(ConfigurableApplicationContext context) {
|
||||
for (ApplicationListener<?> listener : this.application.getListeners()) {
|
||||
if (listener instanceof ApplicationContextAware) {
|
||||
((ApplicationContextAware) listener).setApplicationContext(context);
|
||||
}
|
||||
context.addApplicationListener(listener);
|
||||
}
|
||||
publishEvent(new ApplicationPreparedEvent(this.application, this.args, context));
|
||||
|
|
|
|||
Loading…
Reference in New Issue