docs
This documentation has been enhanced for AI coding agents with comprehensive examples, complete API signatures, thread safety notes, error handling patterns, and production-ready usage patterns.
| Event Class | When Published | Thread Safety | ApplicationContext Available | Key Use Cases |
|---|---|---|---|---|
ApplicationStartingEvent | Very early, before Environment/Context | Thread-safe (immutable) | No | Very early initialization, bootstrap registry setup |
ApplicationEnvironmentPreparedEvent | Environment ready | Thread-safe (immutable) | No | Add/modify property sources, Environment validation |
ApplicationContextInitializedEvent | Context created, initializers called | Thread-safe (immutable) | Yes (unprepared) | Context configuration before bean loading |
ApplicationPreparedEvent | Context prepared, beans not instantiated | Thread-safe (immutable) | Yes (prepared) | Final bean definition modifications |
ApplicationStartedEvent | Context refreshed, before runners | Thread-safe (immutable) | Yes (refreshed) | Access initialized beans, startup tasks |
ApplicationReadyEvent | Application fully ready | Thread-safe (immutable) | Yes (running) | Trigger readiness indicators, start scheduled tasks |
ApplicationFailedEvent | Startup failure occurred | Thread-safe (immutable) | Maybe | Error handling, cleanup, failure notifications |
| Component | Purpose | Thread Safety | Key Use Cases |
|---|---|---|---|
BootstrapRegistry | Register instances for early access | Thread-safe | Register expensive objects before ApplicationContext |
BootstrapContext | Read-only access to registry | Thread-safe | Retrieve registered instances |
ConfigurableBootstrapContext | Read-write access | Thread-safe | Full bootstrap context access |
BootstrapRegistryInitializer | Initialize bootstrap registry | N/A | Programmatic registration |
BootstrapContextClosedEvent | Bootstrap context closure notification | Thread-safe (immutable) | Migrate instances to ApplicationContext |
| Method | When Called | Environment Available | Context Available |
|---|---|---|---|
starting() | Very first | No | No |
environmentPrepared() | Environment ready | Yes | No |
contextPrepared() | Context created | Yes | Yes (unprepared) |
contextLoaded() | Bean definitions loaded | Yes | Yes (unrefreshed) |
started() | Context refreshed | Yes | Yes (refreshed) |
ready() | Fully ready | Yes | Yes (running) |
failed() | On failure | Depends | Depends |
This document provides comprehensive coverage of Spring Boot's application lifecycle event system, including all lifecycle event classes, the SpringApplicationRunListener interface, bootstrap context support, and related components.
Spring Boot provides a comprehensive lifecycle event system that allows applications to hook into various stages of the application startup and shutdown process. The lifecycle follows this sequence:
All lifecycle events extend from SpringApplicationEvent, which itself extends Spring's ApplicationEvent.
The base class for all Spring Boot application lifecycle events.
package org.springframework.boot.context.event;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationEvent;
/**
* Base class for {@link ApplicationEvent} related to a {@link SpringApplication}.
* Provides access to the SpringApplication instance and command-line arguments
* that were passed during application startup.
*
* @author Phillip Webb
* @since 1.0.0
*/
@SuppressWarnings("serial")
public abstract class SpringApplicationEvent extends ApplicationEvent {
private final String[] args;
/**
* Create a new SpringApplicationEvent.
* @param application the SpringApplication instance (source of the event)
* @param args the command-line arguments
*/
public SpringApplicationEvent(SpringApplication application, String[] args) {
super(application);
this.args = args;
}
/**
* Return the SpringApplication associated with the event.
* @return the SpringApplication instance
*/
public SpringApplication getSpringApplication() {
return (SpringApplication) getSource();
}
/**
* Return the command-line arguments.
* @return the arguments array
*/
public final String[] getArgs() {
return this.args;
}
}ApplicationEventSpringApplication instancePublished as early as conceivably possible when a SpringApplication has been started. This is before the Environment or ApplicationContext is available, but after ApplicationListeners have been registered.
package org.springframework.boot.context.event;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
/**
* Event published as early as conceivably possible as soon as a {@link SpringApplication}
* has been started - before the {@link Environment} or {@link ApplicationContext} is
* available, but after the {@link ApplicationListener}s have been registered.
*
* The source of the event is the {@link SpringApplication} itself, but beware of using
* its internal state too much at this early stage since it might be modified later in
* the lifecycle.
*
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.5.0
*/
@SuppressWarnings("serial")
public class ApplicationStartingEvent extends SpringApplicationEvent {
private final ConfigurableBootstrapContext bootstrapContext;
/**
* Create a new {@link ApplicationStartingEvent} instance.
* @param bootstrapContext the bootstrap context
* @param application the current application
* @param args the arguments the application is running with
*/
public ApplicationStartingEvent(ConfigurableBootstrapContext bootstrapContext,
SpringApplication application,
String[] args) {
super(application, args);
this.bootstrapContext = bootstrapContext;
}
/**
* Return the bootstrap context.
* @return the bootstrap context
* @since 2.4.0
*/
public ConfigurableBootstrapContext getBootstrapContext() {
return this.bootstrapContext;
}
}Published when a SpringApplication is starting up and the Environment is first available for inspection and modification.
package org.springframework.boot.context.event;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* Event published when a {@link SpringApplication} is starting up and the
* {@link Environment} is first available for inspection and modification.
*
* This event is published after the Environment has been prepared but before
* the ApplicationContext has been created. It's the ideal time to customize
* the Environment.
*
* @author Dave Syer
* @since 1.0.0
*/
@SuppressWarnings("serial")
public class ApplicationEnvironmentPreparedEvent extends SpringApplicationEvent {
private final ConfigurableBootstrapContext bootstrapContext;
private final ConfigurableEnvironment environment;
/**
* Create a new {@link ApplicationEnvironmentPreparedEvent} instance.
* @param bootstrapContext the bootstrap context
* @param application the current application
* @param args the arguments the application is running with
* @param environment the environment that was just created
*/
public ApplicationEnvironmentPreparedEvent(ConfigurableBootstrapContext bootstrapContext,
SpringApplication application,
String[] args,
ConfigurableEnvironment environment) {
super(application, args);
this.bootstrapContext = bootstrapContext;
this.environment = environment;
}
/**
* Return the bootstrap context.
* @return the bootstrap context
* @since 2.4.0
*/
public ConfigurableBootstrapContext getBootstrapContext() {
return this.bootstrapContext;
}
/**
* Return the environment.
* @return the environment
*/
public ConfigurableEnvironment getEnvironment() {
return this.environment;
}
}EnvironmentPostProcessor logicPublished when a SpringApplication is starting up and the ApplicationContext is prepared. ApplicationContextInitializers have been called but before any bean definitions are loaded.
package org.springframework.boot.context.event;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Event published when a {@link SpringApplication} is starting up and the
* {@link ApplicationContext} is prepared and ApplicationContextInitializers have been
* called but before any bean definitions are loaded.
*
* This provides an opportunity to perform operations on the ApplicationContext
* after it has been initialized but before beans are defined.
*
* @author Artsiom Yudovin
* @since 2.1.0
*/
@SuppressWarnings("serial")
public class ApplicationContextInitializedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
/**
* Create a new {@link ApplicationContextInitializedEvent} instance.
* @param application the current application
* @param args the arguments the application is running with
* @param context the context that has been initialized
*/
public ApplicationContextInitializedEvent(SpringApplication application,
String[] args,
ConfigurableApplicationContext context) {
super(application, args);
this.context = context;
}
/**
* Return the application context.
* @return the context
*/
public ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
}Published when a SpringApplication is starting up and the ApplicationContext is fully prepared but not refreshed. Bean definitions are loaded and the Environment is ready for use.
package org.springframework.boot.context.event;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
/**
* Event published when a {@link SpringApplication} is starting up and the
* {@link ApplicationContext} is fully prepared but not refreshed. The bean definitions
* will be loaded and the {@link Environment} is ready for use at this stage.
*
* This is the last opportunity to perform operations before the ApplicationContext
* is refreshed and beans are instantiated.
*
* @author Dave Syer
* @since 1.0.0
*/
@SuppressWarnings("serial")
public class ApplicationPreparedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
/**
* Create a new {@link ApplicationPreparedEvent} instance.
* @param application the current application
* @param args the arguments the application is running with
* @param context the ApplicationContext about to be refreshed
*/
public ApplicationPreparedEvent(SpringApplication application,
String[] args,
ConfigurableApplicationContext context) {
super(application, args);
this.context = context;
}
/**
* Return the application context.
* @return the context
*/
public ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
}Published once the application context has been refreshed but before any ApplicationRunner and CommandLineRunner have been called.
package org.springframework.boot.context.event;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Event published once the application context has been refreshed but before any
* {@link ApplicationRunner application} and {@link CommandLineRunner command line}
* runners have been called.
*
* This event indicates that the application is fully started and all beans are
* instantiated, but custom runners haven't executed yet.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
@SuppressWarnings("serial")
public class ApplicationStartedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
private final @Nullable Duration timeTaken;
/**
* Create a new {@link ApplicationStartedEvent} instance.
* @param application the current application
* @param args the arguments the application is running with
* @param context the context that was being created
* @param timeTaken the time taken to start the application, or null if unknown
* @since 2.6.0
*/
public ApplicationStartedEvent(SpringApplication application,
String[] args,
ConfigurableApplicationContext context,
@Nullable Duration timeTaken) {
super(application, args);
this.context = context;
this.timeTaken = timeTaken;
}
/**
* Return the application context.
* @return the context
*/
public ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
/**
* Return the time taken to start the application, or {@code null} if unknown.
* @return the startup time
* @since 2.6.0
*/
public @Nullable Duration getTimeTaken() {
return this.timeTaken;
}
}Published as late as conceivably possible to indicate that the application is ready to service requests. The source of the event is the SpringApplication itself.
package org.springframework.boot.context.event;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Event published as late as conceivably possible to indicate that the application is
* ready to service requests. The source of the event is the {@link SpringApplication}
* itself, but beware of modifying its internal state since all initialization steps will
* have been completed by then.
*
* This is the final event in the successful startup sequence, published after all
* CommandLineRunners and ApplicationRunners have been called.
*
* @author Stephane Nicoll
* @author Chris Bono
* @since 1.3.0
* @see ApplicationFailedEvent
*/
@SuppressWarnings("serial")
public class ApplicationReadyEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
private final @Nullable Duration timeTaken;
/**
* Create a new {@link ApplicationReadyEvent} instance.
* @param application the current application
* @param args the arguments the application is running with
* @param context the context that was being created
* @param timeTaken the time taken to get the application ready to service requests,
* or null if unknown
* @since 2.6.0
*/
public ApplicationReadyEvent(SpringApplication application,
String[] args,
ConfigurableApplicationContext context,
@Nullable Duration timeTaken) {
super(application, args);
this.context = context;
this.timeTaken = timeTaken;
}
/**
* Return the application context.
* @return the context
*/
public ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
/**
* Return the time taken for the application to be ready to service requests,
* or {@code null} if unknown.
* @return the time taken to be ready to service requests
* @since 2.6.0
*/
public @Nullable Duration getTimeTaken() {
return this.timeTaken;
}
}Published by a SpringApplication when it fails to start. This event can be published at any point during the startup sequence if a failure occurs.
package org.springframework.boot.context.event;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Event published by a {@link SpringApplication} when it fails to start.
*
* This event is published whenever a failure occurs during the application startup
* process. The ApplicationContext may or may not be available depending on when
* the failure occurred.
*
* @author Dave Syer
* @since 1.0.0
* @see ApplicationReadyEvent
*/
@SuppressWarnings("serial")
public class ApplicationFailedEvent extends SpringApplicationEvent {
private final @Nullable ConfigurableApplicationContext context;
private final Throwable exception;
/**
* Create a new {@link ApplicationFailedEvent} instance.
* @param application the current application
* @param args the arguments the application was running with
* @param context the context that was being created (may be null if failure
* occurred before context creation)
* @param exception the exception that caused the failure
*/
public ApplicationFailedEvent(SpringApplication application,
String[] args,
@Nullable ConfigurableApplicationContext context,
Throwable exception) {
super(application, args);
this.context = context;
this.exception = exception;
}
/**
* Return the application context.
* @return the context or {@code null} if the failure occurred before
* context creation
*/
public @Nullable ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
/**
* Return the exception that caused the failure.
* @return the exception
*/
public Throwable getException() {
return this.exception;
}
}Interface for listening to the SpringApplication run method lifecycle. Listeners are loaded via SpringFactoriesLoader and should declare a public constructor accepting a SpringApplication instance and String[] arguments.
package org.springframework.boot;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;
/**
* Listener for the {@link SpringApplication} {@code run} method.
* {@link SpringApplicationRunListener}s are loaded through the
* {@link SpringFactoriesLoader} and should declare a public constructor that accepts a
* {@link SpringApplication} instance and a {@code String[]} of arguments. A new
* {@link SpringApplicationRunListener} instance will be created for each run.
*
* This interface provides a lower-level alternative to listening for application events.
* It's particularly useful when you need to perform actions that can't wait for the
* ApplicationContext to be available.
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
* @author Chris Bono
* @since 1.0.0
*/
public interface SpringApplicationRunListener {
/**
* Called immediately when the run method has first started. Can be used for very
* early initialization.
*
* At this point:
* - The bootstrap context is available
* - ApplicationListeners have been registered
* - The Environment has not been created yet
* - The ApplicationContext has not been created yet
*
* @param bootstrapContext the bootstrap context
*/
default void starting(ConfigurableBootstrapContext bootstrapContext) {
}
/**
* Called once the environment has been prepared, but before the
* {@link ApplicationContext} has been created.
*
* At this point:
* - The Environment is fully prepared and can be modified
* - Property sources have been loaded
* - Profiles have been activated
* - The ApplicationContext has not been created yet
*
* @param bootstrapContext the bootstrap context
* @param environment the environment
*/
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
}
/**
* Called once the {@link ApplicationContext} has been created and prepared, but
* before sources have been loaded.
*
* At this point:
* - The ApplicationContext has been created
* - ApplicationContextInitializers have been called
* - Bean definitions have not been loaded yet
*
* @param context the application context
*/
default void contextPrepared(ConfigurableApplicationContext context) {
}
/**
* Called once the application context has been loaded but before it has been
* refreshed.
*
* At this point:
* - Bean definitions have been loaded
* - The context has not been refreshed yet
* - Beans have not been instantiated yet
*
* @param context the application context
*/
default void contextLoaded(ConfigurableApplicationContext context) {
}
/**
* The context has been refreshed and the application has started but
* {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
* ApplicationRunners} have not been called.
*
* At this point:
* - The ApplicationContext has been refreshed
* - All beans have been instantiated
* - Runners have not been called yet
*
* @param context the application context
* @param timeTaken the time taken to start the application or {@code null} if unknown
* @since 2.6.0
*/
default void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
}
/**
* Called immediately before the run method finishes, when the application context has
* been refreshed and all {@link CommandLineRunner CommandLineRunners} and
* {@link ApplicationRunner ApplicationRunners} have been called.
*
* At this point:
* - The application is fully started
* - All runners have been executed
* - The application is ready to service requests
*
* @param context the application context
* @param timeTaken the time taken for the application to be ready or {@code null} if
* unknown
* @since 2.6.0
*/
default void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
}
/**
* Called when a failure occurs when running the application.
*
* This method is called if any exception occurs during the application startup
* process. The ApplicationContext may or may not be available depending on when
* the failure occurred.
*
* @param context the application context or {@code null} if a failure occurred before
* the context was created
* @param exception the failure
* @since 2.0.0
*/
default void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
}
}To register a custom SpringApplicationRunListener, add it to META-INF/spring.factories:
org.springframework.boot.SpringApplicationRunListener=\
com.example.MyCustomRunListenerThe bootstrap context system provides a way to register and share expensive objects during the early stages of application startup, before the main ApplicationContext is available.
Interface for registering objects in the bootstrap context.
package org.springframework.boot.bootstrap;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
/**
* A simple object registry that is available during startup and {@link Environment}
* post-processing up to the point that the {@link ApplicationContext} is prepared.
*
* Can be used to register instances that may be expensive to create, or need to be shared
* before the {@link ApplicationContext} is available.
*
* The registry uses {@link Class} as a key, meaning that only a single instance of a
* given type can be stored.
*
* The {@link #addCloseListener(ApplicationListener)} method can be used to add a listener
* that can perform actions when {@link BootstrapContext} has been closed and the
* {@link ApplicationContext} is fully prepared. For example, an instance may choose to
* register itself as a regular Spring bean so that it is available for the application to
* use.
*
* @author Phillip Webb
* @since 4.0.0
* @see BootstrapContext
* @see ConfigurableBootstrapContext
*/
public interface BootstrapRegistry {
/**
* Register a specific type with the registry. If the specified type has already been
* registered and has not been obtained as a {@link Scope#SINGLETON singleton}, it
* will be replaced.
*
* @param <T> the instance type
* @param type the instance type
* @param instanceSupplier the instance supplier
*/
<T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier);
/**
* Register a specific type with the registry if one is not already present.
*
* @param <T> the instance type
* @param type the instance type
* @param instanceSupplier the instance supplier
*/
<T> void registerIfAbsent(Class<T> type, InstanceSupplier<T> instanceSupplier);
/**
* Return if a registration exists for the given type.
*
* @param <T> the instance type
* @param type the instance type
* @return {@code true} if the type has already been registered
*/
<T> boolean isRegistered(Class<T> type);
/**
* Return any existing {@link InstanceSupplier} for the given type.
*
* @param <T> the instance type
* @param type the instance type
* @return the registered {@link InstanceSupplier} or {@code null}
*/
<T> @Nullable InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
/**
* Add an {@link ApplicationListener} that will be called with a
* {@link BootstrapContextClosedEvent} when the {@link BootstrapContext} is closed and
* the {@link ApplicationContext} has been prepared.
*
* @param listener the listener to add
*/
void addCloseListener(ApplicationListener<BootstrapContextClosedEvent> listener);
/**
* Supplier used to provide the actual instance when needed.
*
* @param <T> the instance type
* @see Scope
*/
@FunctionalInterface
interface InstanceSupplier<T> {
/**
* Factory method used to create the instance when needed.
*
* @param context the {@link BootstrapContext} which may be used to obtain other
* bootstrap instances
* @return the instance or {@code null}
*/
@Nullable T get(BootstrapContext context);
/**
* Return the scope of the supplied instance.
*
* @return the scope (defaults to SINGLETON)
*/
default Scope getScope() {
return Scope.SINGLETON;
}
/**
* Return a new {@link InstanceSupplier} with an updated {@link Scope}.
*
* @param scope the new scope
* @return a new {@link InstanceSupplier} instance with the new scope
*/
default InstanceSupplier<T> withScope(Scope scope) {
Assert.notNull(scope, "'scope' must not be null");
InstanceSupplier<T> parent = this;
return new InstanceSupplier<>() {
@Override
public @Nullable T get(BootstrapContext context) {
return parent.get(context);
}
@Override
public Scope getScope() {
return scope;
}
};
}
/**
* Factory method that can be used to create an {@link InstanceSupplier} for a
* given instance.
*
* @param <T> the instance type
* @param instance the instance
* @return a new {@link InstanceSupplier}
*/
static <T> InstanceSupplier<T> of(@Nullable T instance) {
return (registry) -> instance;
}
/**
* Factory method that can be used to create an {@link InstanceSupplier} from a
* {@link Supplier}.
*
* @param <T> the instance type
* @param supplier the supplier that will provide the instance
* @return a new {@link InstanceSupplier}
*/
static <T> InstanceSupplier<T> from(@Nullable Supplier<T> supplier) {
return (registry) -> (supplier != null) ? supplier.get() : null;
}
}
/**
* The scope of an instance.
*/
enum Scope {
/**
* A singleton instance. The {@link InstanceSupplier} will be called only once and
* the same instance will be returned each time.
*/
SINGLETON,
/**
* A prototype instance. The {@link InstanceSupplier} will be called whenever an
* instance is needed.
*/
PROTOTYPE
}
}Interface providing read-only access to the bootstrap context.
package org.springframework.boot.bootstrap;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
/**
* A simple bootstrap context that is available during startup and {@link Environment}
* post-processing up to the point that the {@link ApplicationContext} is prepared.
*
* Provides lazy access to singletons that may be expensive to create, or need to be
* shared before the {@link ApplicationContext} is available.
*
* Instances are registered by type. The context may return {@code null} values when a
* type has been registered but no value is actually supplied.
*
* @author Phillip Webb
* @since 4.0.0
* @see BootstrapRegistry
*/
public interface BootstrapContext {
/**
* Return an instance from the context if the type has been registered. The instance
* will be created if it hasn't been accessed previously.
*
* @param <T> the instance type
* @param type the instance type
* @return the instance managed by the context, which may be {@code null}
* @throws IllegalStateException if the type has not been registered
*/
<T> @Nullable T get(Class<T> type) throws IllegalStateException;
/**
* Return an instance from the context if the type has been registered. The instance
* will be created if it hasn't been accessed previously.
*
* @param <T> the instance type
* @param type the instance type
* @param other the instance to use if the type has not been registered
* @return the instance, which may be {@code null}
*/
<T> @Nullable T getOrElse(Class<T> type, @Nullable T other);
/**
* Return an instance from the context if the type has been registered. The instance
* will be created if it hasn't been accessed previously.
*
* @param <T> the instance type
* @param type the instance type
* @param other a supplier for the instance to use if the type has not been registered
* @return the instance, which may be {@code null}
*/
<T> @Nullable T getOrElseSupply(Class<T> type, Supplier<@Nullable T> other);
/**
* Return an instance from the context if the type has been registered. The instance
* will be created if it hasn't been accessed previously.
*
* @param <T> the instance type
* @param <X> the exception to throw if the type is not registered
* @param type the instance type
* @param exceptionSupplier the supplier which will return the exception to be thrown
* @return the instance managed by the context, which may be {@code null}
* @throws X if the type has not been registered
*/
<T, X extends Throwable> @Nullable T getOrElseThrow(Class<T> type,
Supplier<? extends X> exceptionSupplier)
throws X;
/**
* Return if a registration exists for the given type.
*
* @param <T> the instance type
* @param type the instance type
* @return {@code true} if the type has already been registered
*/
<T> boolean isRegistered(Class<T> type);
}Combines BootstrapRegistry and BootstrapContext for full read-write access.
package org.springframework.boot.bootstrap;
/**
* A {@link BootstrapContext} that also provides configuration methods through the
* {@link BootstrapRegistry} interface.
*
* This interface combines the read capabilities of BootstrapContext with the write
* capabilities of BootstrapRegistry, providing full access to the bootstrap context
* during the early stages of application startup.
*
* @author Phillip Webb
* @since 4.0.0
* @see BootstrapRegistry
* @see BootstrapContext
* @see DefaultBootstrapContext
*/
public interface ConfigurableBootstrapContext extends BootstrapRegistry, BootstrapContext {
}Callback interface for initializing a BootstrapRegistry before it is used.
package org.springframework.boot.bootstrap;
/**
* Callback interface that can be used to initialize a {@link BootstrapRegistry} before it
* is used.
*
* This interface is typically implemented by classes that need to register instances
* in the bootstrap registry during the very early stages of application startup.
* Implementations are loaded via SpringFactoriesLoader or can be added programmatically
* to SpringApplication.
*
* @author Phillip Webb
* @since 4.0.0
* @see BootstrapRegistry
*/
@FunctionalInterface
public interface BootstrapRegistryInitializer {
/**
* Initialize the given {@link BootstrapRegistry} with any required registrations.
*
* This method is called very early in the application lifecycle, before the
* Environment is prepared. Use it to register instances that may be needed
* during environment preparation or context initialization.
*
* @param registry the registry to initialize
*/
void initialize(BootstrapRegistry registry);
}Implementations can be registered in META-INF/spring.factories:
org.springframework.boot.BootstrapRegistryInitializer=\
com.example.MyBootstrapRegistryInitializerOr programmatically:
SpringApplication app = new SpringApplication(MyApplication.class);
app.addBootstrapRegistryInitializer(registry -> {
// Register instances
});Event published when the BootstrapContext is closed and the ApplicationContext has been prepared.
package org.springframework.boot.bootstrap;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
/**
* {@link ApplicationEvent} published by a {@link BootstrapContext} when it's closed.
*
* This event is published after the BootstrapContext has been closed and the
* ApplicationContext is fully prepared. Listeners can use this event to migrate
* instances from the bootstrap context to the application context, or to perform
* cleanup operations.
*
* @author Phillip Webb
* @since 4.0.0
* @see BootstrapRegistry#addCloseListener(org.springframework.context.ApplicationListener)
*/
public class BootstrapContextClosedEvent extends ApplicationEvent {
private final ConfigurableApplicationContext applicationContext;
/**
* Create a new {@link BootstrapContextClosedEvent} instance.
*
* @param source the BootstrapContext that was closed
* @param applicationContext the prepared application context
*/
BootstrapContextClosedEvent(BootstrapContext source,
ConfigurableApplicationContext applicationContext) {
super(source);
this.applicationContext = applicationContext;
}
/**
* Return the {@link BootstrapContext} that was closed.
*
* @return the bootstrap context
*/
public BootstrapContext getBootstrapContext() {
return (BootstrapContext) this.source;
}
/**
* Return the prepared application context.
*
* @return the application context
*/
public ConfigurableApplicationContext getApplicationContext() {
return this.applicationContext;
}
}import org.springframework.boot.context.event.*;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationLifecycleListener {
@EventListener
public void onApplicationStarting(ApplicationStartingEvent event) {
System.out.println("Application is starting...");
System.out.println("Args: " + String.join(", ", event.getArgs()));
}
@EventListener
public void onEnvironmentPrepared(ApplicationEnvironmentPreparedEvent event) {
System.out.println("Environment prepared");
String appName = event.getEnvironment()
.getProperty("spring.application.name");
System.out.println("Application name: " + appName);
}
@EventListener
public void onContextInitialized(ApplicationContextInitializedEvent event) {
System.out.println("Context initialized, ID: "
+ event.getApplicationContext().getId());
}
@EventListener
public void onApplicationPrepared(ApplicationPreparedEvent event) {
System.out.println("Application context prepared");
System.out.println("Bean count: "
+ event.getApplicationContext().getBeanDefinitionCount());
}
@EventListener
public void onApplicationStarted(ApplicationStartedEvent event) {
System.out.println("Application started");
if (event.getTimeTaken() != null) {
System.out.println("Startup time: "
+ event.getTimeTaken().toMillis() + "ms");
}
}
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
System.out.println("Application is ready to service requests");
if (event.getTimeTaken() != null) {
System.out.println("Total time: "
+ event.getTimeTaken().toMillis() + "ms");
}
}
@EventListener
public void onApplicationFailed(ApplicationFailedEvent event) {
System.err.println("Application failed to start");
System.err.println("Exception: " + event.getException().getMessage());
}
}import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationReadyListener
implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("Application is ready!");
// Access the application context
var context = event.getApplicationContext();
String[] beanNames = context.getBeanDefinitionNames();
System.out.println("Total beans: " + beanNames.length);
// Access startup time
if (event.getTimeTaken() != null) {
System.out.println("Ready in: "
+ event.getTimeTaken().toMillis() + "ms");
}
}
}For events that occur before the ApplicationContext is created, you must register the listener directly with SpringApplication:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationStartingEvent;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
// Add listener for early events
app.addListeners(event -> {
if (event instanceof ApplicationStartingEvent) {
System.out.println("Very early initialization");
}
});
app.run(args);
}
}Create a custom run listener to hook into all lifecycle stages:
import org.springframework.boot.*;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.time.Duration;
public class CustomRunListener implements SpringApplicationRunListener {
private final SpringApplication application;
private final String[] args;
// Required constructor
public CustomRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("==> Starting");
// Register instances in bootstrap context if needed
bootstrapContext.register(MyService.class,
context -> new MyService());
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
System.out.println("==> Environment prepared");
// Add custom property sources
String profile = environment.getProperty("spring.profiles.active");
System.out.println("Active profile: " + profile);
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("==> Context prepared");
// Perform context-level initialization
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("==> Context loaded");
// Bean definitions are loaded but not instantiated
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("==> Started in " + timeTaken.toMillis() + "ms");
// All beans are instantiated
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("==> Ready in " + timeTaken.toMillis() + "ms");
// Application is fully ready
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.err.println("==> Failed: " + exception.getMessage());
// Handle startup failure
}
}Register in META-INF/spring.factories:
org.springframework.boot.SpringApplicationRunListener=\
com.example.CustomRunListenerimport org.springframework.boot.BootstrapRegistryInitializer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.bootstrap.BootstrapRegistry;
import org.springframework.boot.context.event.ApplicationStartingEvent;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
// Add bootstrap registry initializer
app.addBootstrapRegistryInitializer(registry -> {
// Register expensive service
registry.register(DatabaseConnectionPool.class,
context -> new DatabaseConnectionPool());
// Register with prototype scope
registry.register(RequestIdGenerator.class,
BootstrapRegistry.InstanceSupplier
.from(() -> new RequestIdGenerator())
.withScope(BootstrapRegistry.Scope.PROTOTYPE));
});
app.run(args);
}
}import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
public class EnvironmentInitializer
implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
// Access bootstrap context
var bootstrapContext = event.getBootstrapContext();
// Get registered instance
DatabaseConnectionPool pool =
bootstrapContext.get(DatabaseConnectionPool.class);
// Use it to initialize environment
if (pool != null) {
event.getEnvironment().getPropertySources()
.addLast(new DatabasePropertySource(pool));
}
}
}import org.springframework.boot.BootstrapRegistryInitializer;
import org.springframework.boot.bootstrap.BootstrapRegistry;
import org.springframework.context.support.GenericApplicationContext;
public class MyBootstrapInitializer implements BootstrapRegistryInitializer {
@Override
public void initialize(BootstrapRegistry registry) {
// Register instance
registry.register(ExpensiveService.class,
context -> new ExpensiveService());
// Add close listener to migrate to ApplicationContext
registry.addCloseListener(event -> {
// Get bootstrap instance
ExpensiveService service =
event.getBootstrapContext().get(ExpensiveService.class);
// Register as Spring bean
GenericApplicationContext appContext =
(GenericApplicationContext) event.getApplicationContext();
appContext.registerBean("expensiveService",
ExpensiveService.class,
() -> service);
});
}
}import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.bootstrap.BootstrapRegistry;
@SpringBootApplication
public class ComplexBootstrapExample {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ComplexBootstrapExample.class);
app.addBootstrapRegistryInitializer(registry -> {
// Register configuration loader
registry.register(ConfigurationLoader.class, context -> {
// Can access other bootstrap instances
Logger logger = context.getOrElse(Logger.class,
new DefaultLogger());
return new ConfigurationLoader(logger);
});
// Register logger
registry.registerIfAbsent(Logger.class,
BootstrapRegistry.InstanceSupplier.of(new DefaultLogger()));
// Add close listener for cleanup
registry.addCloseListener(event -> {
Logger logger = event.getBootstrapContext()
.get(Logger.class);
logger.info("Bootstrap context closed");
// Optionally migrate to ApplicationContext
ConfigurationLoader loader =
event.getBootstrapContext().get(ConfigurationLoader.class);
event.getApplicationContext()
.getBeanFactory()
.registerSingleton("configLoader", loader);
});
});
app.run(args);
}
}Add custom property sources early in the lifecycle to provide configuration from external systems.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class CustomPropertySourceApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CustomPropertySourceApplication.class);
// Register listener for environment preparation
app.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event -> {
ConfigurableEnvironment environment = event.getEnvironment();
// Add custom property source with high priority
Map<String, Object> customProperties = new HashMap<>();
customProperties.put("app.feature.enabled", "true");
customProperties.put("app.external.url", loadExternalUrl());
MapPropertySource propertySource =
new MapPropertySource("customProperties", customProperties);
environment.getPropertySources().addFirst(propertySource);
System.out.println("Custom property source added to environment");
});
app.run(args);
}
private static String loadExternalUrl() {
// Load from external configuration service
return "https://api.example.com";
}
}Use Cases:
Dynamically register beans based on application state during lifecycle events.
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class ConditionalBeanRegistrar
implements ApplicationListener<ApplicationPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
GenericApplicationContext context =
(GenericApplicationContext) event.getApplicationContext();
// Check environment to decide which bean to register
String environment = context.getEnvironment()
.getProperty("spring.profiles.active", "default");
if ("production".equals(environment)) {
// Register production-specific bean
context.registerBean("dataSource", ProductionDataSource.class,
() -> new ProductionDataSource());
} else {
// Register development bean
context.registerBean("dataSource", DevelopmentDataSource.class,
() -> new DevelopmentDataSource());
}
System.out.println("Registered conditional bean for environment: " + environment);
}
}
class ProductionDataSource {
public ProductionDataSource() {
System.out.println("Production DataSource initialized");
}
}
class DevelopmentDataSource {
public DevelopmentDataSource() {
System.out.println("Development DataSource initialized");
}
}Use Cases:
Integrate with health check systems by listening to readiness events.
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@Component
public class HealthCheckIntegration {
private final Path healthCheckFile = Paths.get("/tmp/app-ready");
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
try {
// Create health check file for external monitoring
Files.createFile(healthCheckFile);
// Log readiness with timing
if (event.getTimeTaken() != null) {
System.out.println("Application ready in " +
event.getTimeTaken().toMillis() + "ms");
}
// Notify external monitoring system
notifyHealthCheckSystem(true);
// Update application availability state
System.out.println("Health check indicator created: " + healthCheckFile);
} catch (IOException e) {
System.err.println("Failed to create health check file: " + e.getMessage());
}
}
@EventListener
public void onApplicationFailed(ApplicationFailedEvent event) {
try {
// Remove health check file on failure
Files.deleteIfExists(healthCheckFile);
// Notify monitoring system of failure
notifyHealthCheckSystem(false);
System.err.println("Application failed to start: " +
event.getException().getMessage());
} catch (IOException e) {
System.err.println("Failed to cleanup health check file: " + e.getMessage());
}
}
private void notifyHealthCheckSystem(boolean healthy) {
// Notify external health check system (e.g., Kubernetes readiness probe)
System.out.println("Health status: " + (healthy ? "READY" : "FAILED"));
}
}Use Cases:
Use the bootstrap registry to share expensive objects across early initialization stages.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.bootstrap.BootstrapRegistry;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import java.util.concurrent.atomic.AtomicBoolean;
@SpringBootApplication
public class BootstrapRegistryExample {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BootstrapRegistryExample.class);
// Register expensive service in bootstrap registry
app.addBootstrapRegistryInitializer(registry -> {
registry.register(ExpensiveCryptoService.class, context -> {
System.out.println("Initializing expensive crypto service...");
return new ExpensiveCryptoService();
});
// Add close listener to migrate to ApplicationContext
registry.addCloseListener(event -> {
ExpensiveCryptoService service =
event.getBootstrapContext().get(ExpensiveCryptoService.class);
// Register as Spring bean
event.getApplicationContext()
.getBeanFactory()
.registerSingleton("cryptoService", service);
System.out.println("Crypto service migrated to ApplicationContext");
});
});
// Use the bootstrap service during environment preparation
app.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event -> {
ExpensiveCryptoService cryptoService =
event.getBootstrapContext().get(ExpensiveCryptoService.class);
// Use service to decrypt configuration
String encryptedPassword = event.getEnvironment()
.getProperty("database.password.encrypted");
if (encryptedPassword != null) {
String decrypted = cryptoService.decrypt(encryptedPassword);
System.setProperty("database.password", decrypted);
}
});
app.run(args);
}
}
class ExpensiveCryptoService {
private final AtomicBoolean initialized = new AtomicBoolean(false);
public ExpensiveCryptoService() {
// Simulate expensive initialization
try {
Thread.sleep(1000);
initialized.set(true);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public String decrypt(String encrypted) {
if (!initialized.get()) {
throw new IllegalStateException("Service not initialized");
}
// Simplified decryption
return "decrypted_" + encrypted;
}
}Use Cases:
Track application startup metrics across all lifecycle stages.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
public class StartupMetricsListener implements SpringApplicationRunListener {
private final SpringApplication application;
private final String[] args;
private final Map<String, Instant> timestamps = new HashMap<>();
// Required constructor
public StartupMetricsListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
timestamps.put("init", Instant.now());
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
timestamps.put("starting", Instant.now());
logDuration("Initialization to starting", "init", "starting");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
timestamps.put("environmentPrepared", Instant.now());
logDuration("Starting to environment prepared", "starting", "environmentPrepared");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
timestamps.put("contextPrepared", Instant.now());
logDuration("Environment to context prepared", "environmentPrepared", "contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
timestamps.put("contextLoaded", Instant.now());
logDuration("Context prepared to loaded", "contextPrepared", "contextLoaded");
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
timestamps.put("started", Instant.now());
logDuration("Context loaded to started", "contextLoaded", "started");
System.out.println("==> Total time to started: " + timeTaken);
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
timestamps.put("ready", Instant.now());
logDuration("Started to ready", "started", "ready");
System.out.println("==> Total time to ready: " + timeTaken);
printSummary();
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
timestamps.put("failed", Instant.now());
System.err.println("==> Application failed at: " + timestamps.get("failed"));
System.err.println("==> Exception: " + exception.getMessage());
printSummary();
}
private void logDuration(String phase, String startKey, String endKey) {
Instant start = timestamps.get(startKey);
Instant end = timestamps.get(endKey);
if (start != null && end != null) {
Duration duration = Duration.between(start, end);
System.out.println(String.format("==> %s: %dms", phase, duration.toMillis()));
}
}
private void printSummary() {
System.out.println("\n=== Startup Metrics Summary ===");
timestamps.forEach((key, value) ->
System.out.println(key + ": " + value));
}
}Register in META-INF/spring.factories:
org.springframework.boot.SpringApplicationRunListener=\
com.example.StartupMetricsListenerUse Cases:
@Async for non-critical operations in later events@Component
public class RobustEventListener {
private static final Logger log = LoggerFactory.getLogger(RobustEventListener.class);
@EventListener
public void onEnvironmentPrepared(ApplicationEnvironmentPreparedEvent event) {
try {
// Perform operation that might fail
loadExternalConfiguration(event.getEnvironment());
} catch (Exception e) {
log.error("Failed to load external configuration", e);
// Decide: fail-fast or continue with degraded functionality
throw new IllegalStateException("Critical configuration missing", e);
}
}
private void loadExternalConfiguration(ConfigurableEnvironment environment) {
// Implementation
}
}import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@ExtendWith(SpringExtension.class)
class LifecycleEventTest {
private static final AtomicBoolean readyEventReceived = new AtomicBoolean(false);
@TestConfiguration
static class TestConfig {
@EventListener
public void onReady(ApplicationReadyEvent event) {
readyEventReceived.set(true);
}
}
@Test
void shouldReceiveApplicationReadyEvent() {
assertThat(readyEventReceived.get()).isTrue();
}
}Built-in ApplicationContextInitializer that sets the Spring ApplicationContext ID based on the spring.application.name property.
package org.springframework.boot.context;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
/**
* {@link ApplicationContextInitializer} that sets the Spring
* {@link ApplicationContext#getId() ApplicationContext ID}. The
* {@code spring.application.name} property is used to create the ID. If the property is
* not set {@code application} is used.
*
* @since 1.0.0
*/
public class ContextIdApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
/**
* Set the order for this initializer.
*
* @param order the order value
*/
public void setOrder(int order);
/**
* Get the order value for this initializer.
*
* @return the order value (defaults to Ordered.LOWEST_PRECEDENCE - 10)
*/
@Override
int getOrder();
/**
* Initialize the ApplicationContext by setting its ID.
* The ID is derived from the {@code spring.application.name} property,
* or defaults to "application" if not set.
*
* For child contexts (when a parent context exists), the ID is appended
* with a sequential number (e.g., "myapp-1", "myapp-2").
*
* @param applicationContext the application context to initialize
*/
@Override
void initialize(ConfigurableApplicationContext applicationContext);
}spring.application.namespring.application.name is not configuredThis initializer is automatically registered by Spring Boot and runs during context initialization. The context ID can be accessed programmatically:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@Component
class ContextIdChecker {
private final ApplicationContext context;
public ContextIdChecker(ApplicationContext context) {
this.context = context;
}
@EventListener(ApplicationReadyEvent.class)
public void checkContextId() {
System.out.println("ApplicationContext ID: " + context.getId());
// Output: "myapp" (if spring.application.name=myapp)
// Output: "application" (if spring.application.name not set)
}
}Set the application name in application.properties or application.yml:
# application.properties
spring.application.name=myapp# application.yml
spring:
application:
name: myappimport org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class CustomContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
// Context ID is already set by ContextIdApplicationContextInitializer
String contextId = context.getId();
System.out.println("Initializing context: " + contextId);
// Perform custom initialization based on context ID
if (contextId.startsWith("myapp")) {
// Application-specific initialization
}
}
}