Commit 999748bd authored by Dave Syer's avatar Dave Syer

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
parent d2b88d74
......@@ -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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment