是的,Spring 应用程序上下文会递归地将事件从子上下文传播到其所有祖先。
以下AbstractApplicationContext 代码对此负责:
/**
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
正如您在publishMethod 正文的末尾看到的,如果有父级,那么任何事件也会传播到它。
相反,来自父级的事件不会传播给子级,因为父级不知道子级。
如果您不想传播事件,您可以简单地执行此操作(而不是为您的子上下文设置父级):
yourChildApplicationContext.addBeanFactoryPostProcessor(beanFactory -> {
beanFactory.setParentBeanFactory(parentContext.getBeanFactory());
});
或者,如果您的子上下文是 GenericApplicationContext(AnnotationConfigApplicationContext、GenericGroovyApplicationContext、GenericXmlApplicationContext、StaticApplicationContext),您甚至可以进一步简化:
yourChildApplicationContext.getDefaultListableBeanFactory()
.setParentBeanFactory(parentContext.getBeanFactory());