Skip to content

Commit 999748b

Browse files
author
Dave Syer
committed
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
1 parent d2b88d7 commit 999748b

File tree

4 files changed

+60
-10
lines changed

4 files changed

+60
-10
lines changed

spring-boot/src/main/java/org/springframework/boot/builder/ParentContextApplicationContextInitializer.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ public int getOrder() {
5353

5454
@Override
5555
public void initialize(ConfigurableApplicationContext applicationContext) {
56-
applicationContext.setParent(this.parent);
57-
applicationContext.addApplicationListener(EventPublisher.INSTANCE);
56+
if (applicationContext != this.parent) {
57+
applicationContext.setParent(this.parent);
58+
applicationContext.addApplicationListener(EventPublisher.INSTANCE);
59+
}
5860
}
5961

6062
private static class EventPublisher implements
@@ -70,7 +72,8 @@ public int getOrder() {
7072
@Override
7173
public void onApplicationEvent(ContextRefreshedEvent event) {
7274
ApplicationContext context = event.getApplicationContext();
73-
if (context instanceof ConfigurableApplicationContext) {
75+
if (context instanceof ConfigurableApplicationContext
76+
&& context == event.getSource()) {
7477
context.publishEvent(new ParentContextAvailableEvent(
7578
(ConfigurableApplicationContext) context));
7679
}

spring-boot/src/main/java/org/springframework/boot/builder/ParentContextCloserApplicationListener.java

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
import java.lang.ref.WeakReference;
2020

21+
import org.springframework.beans.BeansException;
2122
import org.springframework.boot.builder.ParentContextApplicationContextInitializer.ParentContextAvailableEvent;
23+
import org.springframework.context.ApplicationContext;
24+
import org.springframework.context.ApplicationContextAware;
2225
import org.springframework.context.ApplicationListener;
2326
import org.springframework.context.ConfigurableApplicationContext;
2427
import org.springframework.context.event.ContextClosedEvent;
@@ -33,11 +36,21 @@
3336
* @author Eric Bottard
3437
*/
3538
public class ParentContextCloserApplicationListener implements
36-
ApplicationListener<ParentContextAvailableEvent>, Ordered {
39+
ApplicationListener<ParentContextAvailableEvent>, ApplicationContextAware,
40+
Ordered {
41+
42+
private int order = Ordered.LOWEST_PRECEDENCE - 10;
43+
44+
private ApplicationContext context;
3745

3846
@Override
3947
public int getOrder() {
40-
return Ordered.LOWEST_PRECEDENCE - 10;
48+
return this.order;
49+
}
50+
51+
@Override
52+
public void setApplicationContext(ApplicationContext context) throws BeansException {
53+
this.context = context;
4154
}
4255

4356
@Override
@@ -46,10 +59,12 @@ public void onApplicationEvent(ParentContextAvailableEvent event) {
4659
}
4760

4861
private void maybeInstallListenerInParent(ConfigurableApplicationContext child) {
49-
if (child.getParent() instanceof ConfigurableApplicationContext) {
50-
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) child
51-
.getParent();
52-
parent.addApplicationListener(createContextCloserListener(child));
62+
if (child == this.context) {
63+
if (child.getParent() instanceof ConfigurableApplicationContext) {
64+
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) child
65+
.getParent();
66+
parent.addApplicationListener(createContextCloserListener(child));
67+
}
5368
}
5469
}
5570

@@ -82,6 +97,35 @@ public void onApplicationEvent(ContextClosedEvent event) {
8297
}
8398
}
8499

100+
@Override
101+
public int hashCode() {
102+
final int prime = 31;
103+
int result = 1;
104+
result = prime
105+
* result
106+
+ ((this.childContext.get() == null) ? 0 : this.childContext.get()
107+
.hashCode());
108+
return result;
109+
}
110+
111+
@Override
112+
public boolean equals(Object obj) {
113+
if (this == obj)
114+
return true;
115+
if (obj == null)
116+
return false;
117+
if (getClass() != obj.getClass())
118+
return false;
119+
ContextCloserListener other = (ContextCloserListener) obj;
120+
if (this.childContext.get() == null) {
121+
if (other.childContext.get() != null)
122+
return false;
123+
}
124+
else if (!this.childContext.get().equals(other.childContext.get()))
125+
return false;
126+
return true;
127+
}
128+
85129
}
86130

87131
}

spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ public SpringApplicationBuilder parent(ConfigurableApplicationContext parent) {
215215
this.parent = new SpringApplicationBuilder();
216216
this.parent.context = parent;
217217
this.parent.running.set(true);
218-
initializers(new ParentContextApplicationContextInitializer(parent));
219218
return this;
220219
}
221220

spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.beans.factory.BeanFactoryAware;
2020
import org.springframework.boot.SpringApplication;
2121
import org.springframework.boot.SpringApplicationRunListener;
22+
import org.springframework.context.ApplicationContextAware;
2223
import org.springframework.context.ApplicationListener;
2324
import org.springframework.context.ConfigurableApplicationContext;
2425
import org.springframework.context.event.ApplicationEventMulticaster;
@@ -78,6 +79,9 @@ private void registerApplicationEventMulticaster(
7879
@Override
7980
public void contextLoaded(ConfigurableApplicationContext context) {
8081
for (ApplicationListener<?> listener : this.application.getListeners()) {
82+
if (listener instanceof ApplicationContextAware) {
83+
((ApplicationContextAware) listener).setApplicationContext(context);
84+
}
8185
context.addApplicationListener(listener);
8286
}
8387
publishEvent(new ApplicationPreparedEvent(this.application, this.args, context));

0 commit comments

Comments
 (0)