@@ -165,6 +165,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
165
165
/** Parent context */
166
166
private ApplicationContext parent ;
167
167
168
+ /** Environment used by this context */
169
+ private ConfigurableEnvironment environment ;
170
+
168
171
/** BeanFactoryPostProcessors to apply on refresh */
169
172
private final List <BeanFactoryPostProcessor > beanFactoryPostProcessors =
170
173
new ArrayList <BeanFactoryPostProcessor >();
@@ -197,10 +200,10 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
197
200
private ApplicationEventMulticaster applicationEventMulticaster ;
198
201
199
202
/** Statically specified listeners */
200
- private Set <ApplicationListener <?>> applicationListeners = new LinkedHashSet <ApplicationListener <?>>();
203
+ private final Set <ApplicationListener <?>> applicationListeners = new LinkedHashSet <ApplicationListener <?>>();
201
204
202
- /** Environment used by this context; initialized by {@link #createEnvironment()} */
203
- private ConfigurableEnvironment environment ;
205
+ /** ApplicationEvents published early */
206
+ private Set < ApplicationEvent > earlyApplicationEvents ;
204
207
205
208
206
209
/**
@@ -340,7 +343,9 @@ protected void publishEvent(Object event, ResolvableType eventType) {
340
343
if (logger .isTraceEnabled ()) {
341
344
logger .trace ("Publishing event in " + getDisplayName () + ": " + event );
342
345
}
343
- final ApplicationEvent applicationEvent ;
346
+
347
+ // Decorate event as an ApplicationEvent if necessary
348
+ ApplicationEvent applicationEvent ;
344
349
if (event instanceof ApplicationEvent ) {
345
350
applicationEvent = (ApplicationEvent ) event ;
346
351
}
@@ -350,7 +355,16 @@ protected void publishEvent(Object event, ResolvableType eventType) {
350
355
eventType = ResolvableType .forClassWithGenerics (PayloadApplicationEvent .class , event .getClass ());
351
356
}
352
357
}
353
- getApplicationEventMulticaster ().multicastEvent (applicationEvent , eventType );
358
+
359
+ // Multicast right now if possible - or lazily once the multicaster is initialized
360
+ if (this .earlyApplicationEvents != null ) {
361
+ this .earlyApplicationEvents .add (applicationEvent );
362
+ }
363
+ else {
364
+ getApplicationEventMulticaster ().multicastEvent (applicationEvent , eventType );
365
+ }
366
+
367
+ // Publish event via parent context as well...
354
368
if (this .parent != null ) {
355
369
if (this .parent instanceof AbstractApplicationContext ) {
356
370
((AbstractApplicationContext ) this .parent ).publishEvent (event , eventType );
@@ -379,7 +393,7 @@ ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalState
379
393
* @return the internal LifecycleProcessor (never {@code null})
380
394
* @throws IllegalStateException if the context has not been initialized yet
381
395
*/
382
- LifecycleProcessor getLifecycleProcessor () {
396
+ LifecycleProcessor getLifecycleProcessor () throws IllegalStateException {
383
397
if (this .lifecycleProcessor == null ) {
384
398
throw new IllegalStateException ("LifecycleProcessor not initialized - " +
385
399
"call 'refresh' before invoking lifecycle methods via the context: " + this );
@@ -543,6 +557,10 @@ protected void prepareRefresh() {
543
557
// Validate that all properties marked as required are resolvable
544
558
// see ConfigurablePropertyResolver#setRequiredProperties
545
559
getEnvironment ().validateRequiredProperties ();
560
+
561
+ // Allow for the collection of early ApplicationEvents,
562
+ // to be published once the multicaster is available...
563
+ this .earlyApplicationEvents = new LinkedHashSet <ApplicationEvent >();
546
564
}
547
565
548
566
/**
@@ -748,11 +766,21 @@ protected void registerListeners() {
748
766
for (ApplicationListener <?> listener : getApplicationListeners ()) {
749
767
getApplicationEventMulticaster ().addApplicationListener (listener );
750
768
}
769
+
751
770
// Do not initialize FactoryBeans here: We need to leave all regular beans
752
771
// uninitialized to let post-processors apply to them!
753
772
String [] listenerBeanNames = getBeanNamesForType (ApplicationListener .class , true , false );
754
- for (String lisName : listenerBeanNames ) {
755
- getApplicationEventMulticaster ().addApplicationListenerBean (lisName );
773
+ for (String listenerBeanName : listenerBeanNames ) {
774
+ getApplicationEventMulticaster ().addApplicationListenerBean (listenerBeanName );
775
+ }
776
+
777
+ // Publish early application events now that we finally have a multicaster...
778
+ Set <ApplicationEvent > earlyEventsToProcess = this .earlyApplicationEvents ;
779
+ this .earlyApplicationEvents = null ;
780
+ if (earlyEventsToProcess != null ) {
781
+ for (ApplicationEvent earlyEvent : earlyEventsToProcess ) {
782
+ getApplicationEventMulticaster ().multicastEvent (earlyEvent );
783
+ }
756
784
}
757
785
}
758
786
0 commit comments