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:

  1. The ApplicationStartingEvent event is dispatched at the start of execution, but before any processing other than registering listeners and initializers begins.

  2. The ApplicationEnvironmentPreparedEvent event is dispatched when the Environment that will be used in the context is known, but before the context is created.

  3. The ApplicationContextInitializedEvent is dispatched when the ApplicationContext is prepared and ApplicationContextInitializers are called, but before the bean definitions are loaded.

  4. The ApplicationPreparedEvent event is dispatched immediately before start of the update, but after the bean definitions have been loaded.

  5. The ApplicationStartedEvent event is dispatched after the context is updated, but before all application and command runtime tools are invoked lines.

  6. Immediately after this, an AvailabilityChangeEvent event is dispatched with LivenessState.CORRECT to indicate that the application is considered to be running.

  7. The ApplicationReadyEvent event is dispatched after any application and command line runner is invoked.

  8. Immediately afterwards AvailabilityChangeEvent is dispatched with ReadinessState.ACCEPTING_TRAFFIC to indicate that the application is ready to process requests.

  9. 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 when WebServer is ready. ServletWebServerInitializedEvent and ReactiveWebServerInitializedEvent are variants of servlet and reactive server respectively.

  • The ContextRefreshedEvent event is dispatched , if the ApplicationContext is updated.

Often there is no need to use application events, but be aware of their existence may be useful. Internally, Spring Boot uses events to perform various tasks.
Event listeners do not have to perform potentially long-running tasks because they run on a single thread by default. Consider using the application and command line runtime tools instead.

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(…​).

It is often desirable to call 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:

Java

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.
    }
}
Kotlin

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"].
    }
}
Spring Boot also registers 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.

This contract is well suited for tasks that must be performed after the application has started, but before it begins to accept traffic.

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:

Java

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) {
        // do something...
    }
}
Kotlin

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:

Java

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)));
    }
}
Kotlin

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.

If you want to know what HTTP port an application is running on, get a property with the key 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:

Java

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);
    }
}
Kotlin

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.