Introduce ContextRestartedEvent as a subtype of ContextStartedEvent

Prior to this commit, there was no way to differentiate between an
ApplicationContext "start" and "restart" in terms of events. This was
due to the fact that a ContextStartedEvent was fired for both
AbstractApplicationContext.start() and
AbstractApplicationContext.restart().

To assist developers who may wish to differentiate between "start" and
"restart" events, this commit introduces a new ContextRestartedEvent as
a subtype of ContextStartedEvent. In addition,
AbstractApplicationContext.restart() now publishes a
ContextRestartedEvent instead of a ContextStartedEvent.

By making ContextRestartedEvent a subtype of ContextStartedEvent,
applications can still expect ContextStoppedEvent/ContextStartedEvent
event pairs for consistent lifecycle semantics, and they can optionally
check if the ContextStartedEvent is a ContextRestartedEvent.
Alternatively, applications can explicitly react to a
ContextRestartedEvent.

See gh-35168
See gh-35171
Closes gh-35194
This commit is contained in:
Sam Brannen 2025-07-12 16:22:35 +02:00
parent 8eedfdf66a
commit ff1e5a87b3
4 changed files with 48 additions and 1 deletions

View File

@ -0,0 +1,44 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.event;
import org.springframework.context.ApplicationContext;
/**
* Event raised when an {@code ApplicationContext} gets restarted.
*
* <p>Note that {@code ContextRestartedEvent} is a specialization of
* {@link ContextStartedEvent}.
*
* @author Sam Brannen
* @since 7.0
* @see ContextStartedEvent
* @see ContextStoppedEvent
*/
@SuppressWarnings("serial")
public class ContextRestartedEvent extends ContextStartedEvent {
/**
* Create a new {@code ContextRestartedEvent}.
* @param source the {@code ApplicationContext} that has been restarted
* (must not be {@code null})
*/
public ContextRestartedEvent(ApplicationContext source) {
super(source);
}
}

View File

@ -24,6 +24,7 @@ import org.springframework.context.ApplicationContext;
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
* @see ContextRestartedEvent
* @see ContextStoppedEvent
*/
@SuppressWarnings("serial")

View File

@ -25,6 +25,7 @@ import org.springframework.context.ApplicationContext;
* @author Juergen Hoeller
* @since 2.5
* @see ContextStartedEvent
* @see ContextRestartedEvent
*/
@SuppressWarnings("serial")
public class ContextStoppedEvent extends ApplicationContextEvent {

View File

@ -67,6 +67,7 @@ import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextRestartedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
@ -1551,7 +1552,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
@Override
public void restart() {
getLifecycleProcessor().onRestart();
publishEvent(new ContextStartedEvent(this));
publishEvent(new ContextRestartedEvent(this));
}
@Override