In addition to regular Spring Framework events such as ContextRefreshedEvent
,
SpringApplication
sends some additional application events.
Some events are actually fired before the
ApplicationContext
is created, so you cannot register a listener for these events as a
@Bean
annotation. You can register them using SpringApplication.addListeners(…)
or the
SpringApplicationBuilder.listeners(…)
method.
If you need these listeners registered
automatically, regardless of how the application was created, you can add the
META-INF/spring.factories
file to the project and reference the listener(s) using the org.springframework.context.ApplicationListener
,
as shown in the following example:
org.springframework.context.ApplicationListener=com.example.project.MyListener
Application events are sent in the following order as the application runs:
The
ApplicationStartingEvent
event is dispatched at the start of execution, but before any processing other than registering listeners and initializers begins.The
ApplicationEnvironmentPreparedEvent
event is dispatched when theEnvironment
that will be used in the context is known, but before the context is created.The
ApplicationContextInitializedEvent
is dispatched when theApplicationContext
is prepared and ApplicationContextInitializers are called, but before the bean definitions are loaded.The
ApplicationPreparedEvent
event is dispatched immediately before start of the update, but after the bean definitions have been loaded.The
ApplicationStartedEvent
event is dispatched after the context is updated, but before all application and command runtime tools are invoked lines.Immediately after this, an
AvailabilityChangeEvent
event is dispatched withLivenessState.CORRECT
to indicate that the application is considered to be running.The
ApplicationReadyEvent
event is dispatched after any application and command line runner is invoked.Immediately afterwards
AvailabilityChangeEvent
is dispatched withReadinessState.ACCEPTING_TRAFFIC
to indicate that the application is ready to process requests.Event ApplicationFailedEvent
is dispatched if an exception occurs at startup.
The above list only includes SpringApplicationEvent
events that are bound to SpringApplication
.
In addition to these, the following events are also published after ApplicationPreparedEvent
and before
ApplicationStartedEvent
:
WebServerInitializedEvent
Event sent whenWebServer
is ready.ServletWebServerInitializedEvent
andReactiveWebServerInitializedEvent
are variants of servlet and reactive server respectively.The
ContextRefreshedEvent
event is dispatched , if theApplicationContext
is updated.
Application events are dispatched using the Spring Framework's event publishing mechanism. Part of this
mechanism ensures that an event published to listeners in a child context will also be published to listeners in any
ancestor contexts. Therefore, if your application uses a hierarchy of SpringApplication
instances, a
listener may receive multiple instances of the same application event type.
So that a listener can
distinguish an event for its context from an event for a child context , it must request its application context to
be injected, and then compare the injected context with the event context. The context can be injected by
implementing ApplicationContextAware
or, if the listener is a bean, using the @Autowired
annotation.
Web Environment
SpringApplication
attempts to create the desired ApplicationContext
type as you specify. The following algorithm is used to determine WebApplicationType
:
If Spring MVC is present,
AnnotationConfigServletWebServerApplicationContext
If Spring MVC is not present and Spring WebFlux is present,
AnnotationConfigReactiveWebServerApplicationContext
Otherwise
AnnotationConfigApplicationContext
is used
This means that if you use Spring MVC and the new WebClient
from Spring WebFlux in the same
application, Spring MVC will be used by default. You can easily override this by calling setWebApplicationType(WebApplicationType)
.
You can also completely control which ApplicationContext
type is used by calling setApplicationContextClass(…)
.
setWebApplicationType(WebApplicationType.NONE)
when using SpringApplication
in a JUnit test.
Accessing Application Arguments
If you need to access application arguments that were passed to
SpringApplication.run(…)
, you can implement the
org.springframework.boot.ApplicationArguments
bean. The ApplicationArguments
interface
provides access to both raw String[]
arguments and parsed option
and
non-option
arguments , as shown in the following example:
import java.util.List;
import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
if (debug) {
System.out.println(files);
}
// if run with the "--debug logfile.txt" option, ["logfile.txt"] will be output.
}
}
import org.springframework.boot.ApplicationArguments
import org.springframework.stereotype.Component
@Component
class MyBean(args: ApplicationArguments) {
init {
val debug = args.containsOption("debug")
val files = args.nonOptionArgs
if (debug) {
println(files)
}
// if run with "--debug logfile.txt", prints ["logfile.txt"].
}
}
CommandLinePropertySource
in Environment
from Spring. This allows, among other things, to inject individual application arguments using the
@Value
annotation.
Using ApplicationRunner or CommandLineRunner
If you need to execute certain code after running SpringApplication
,
you can implement the ApplicationRunner
or CommandLineRunner
interfaces. Both interfaces
work the same and provide a single run
method that is called just before SpringApplication.run(…)
is completed.
The CommandLineRunner
Interface provides access to application arguments as an array of strings,
while ApplicationRunner
uses the ApplicationArguments
interface discussed earlier. The
following example shows a CommandLineRunner
with a run
method:
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// do something...
}
}
import org.springframework.boot.CommandLineRunner
import org.springframework.stereotype.Component
@Component
class MyCommandLineRunner : CommandLineRunner {
override fun run(vararg args: String) {
// do something...
}
}
If multiple CommandLineRunner
or ApplicationRunner
beans are defined, which must be
called in a specific order, you can optionally implement the org.springframework.core.Ordered
interface or use the org.springframework.core.annotation.Order
annotation.
Exiting an Application
Each SpringApplication
registers a completion interceptor with the JVM to ensure that the ApplicationContext
is closed incrementally upon exit. All standard Spring lifecycle callbacks can be used (for example, the DisposableBean
interface or the @PreDestroy
annotation).
In addition, beans can implement the interface org.springframework.boot.ExitCodeGenerator
if they
need to return a specific exit code when calling SpringApplication.exit()
. This exit code can be
passed to System.exit()
to return it as a status code, as shown in the following example:
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MyApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
}
}
import org.springframework.boot.ExitCodeGenerator
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import kotlin.system.exitProcess
@SpringBootApplication
class MyApplication {
@Bean
fun exitCodeGenerator() = ExitCodeGenerator { 42 }
}
fun main(args: Array<String>) {
exitProcess(SpringApplication.exit(
runApplication<MyApplication>(*args)))
}
In addition, the ExitCodeGenerator
interface can be implemented with exceptions . When such an
exception occurs, Spring Boot returns the exit code passed by the implemented getExitCode()
method.
If there is more than one ExitCodeGenerator
, then the first non-null one generated is used exit code. To
control the order in which generators are called, additionally implement the
org.springframework.core.Ordered
interface or use the
org.springframework.core.annotation.Order
annotation.
Administration Features
You can
enable administration-related features for an application by setting the
spring.application.admin.enabled
property. This will open SpringApplicationAdminMXBean
for the MBeanServer
platform. You
can use this feature to remotely administer your Spring Boot application. This function can also be useful for any
wrapper service implementation.
local.server.port
.
Application startup tracking
During application startup SpringApplication
and ApplicationContext
perform many tasks related to the application lifecycle, bean lifecycle, or even handling application events. With
ApplicationStartup
, the Spring Framework allows you to track the startup sequence of an application
using StartupStep
objects. This data can be collected for profiling purposes or simply to better
understand the application startup process.
You can select the ApplicationStartup
implementation
when configuring your SpringApplication
instance. For example, to use
BufferingApplicationStartup
, you could write:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
}
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args) {
applicationStartup = BufferingApplicationStartup(2048)
}
}
The first available implementation, FlightRecorderApplicationStartup
, is provided by the Spring
Framework. It adds Spring-related startup events to the Java Flight Recorder session and is designed to profile
applications and align the lifecycle of the Spring context with JVM events (such as allocation operations, memory
cleanup operations, class loading...). Once configured, you can record data by launching the application with Flight
Recorder enabled:
$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar
Spring Boot comes with a variation of BufferingApplicationStartup
; this implementation is
designed to buffer startup stages and flush them to an external metrics system. Applications can request a bean of
type BufferingApplicationStartup
in any component.
Spring Boot can also be configured to expose the final dot startup
, which conveys this information
as a JSON document.