Spring Boot startup execution process

Core Process Overview

In Spring Boot applications, we typically write a class containing a main method and call `SpringApplication.run`.
Example code:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

The entire startup process can be summarized as: constructing  SpringApplication an object -> executing  run a method -> starting the embedded server -> completing application startup .


Phase 1: SpringApplication Instantiation

Execution method:new SpringApplication(primarySources)

  1. implement this(null, primarySources) :
    • Function : Calls the internal constructor.
    • The most important part is  WebApplicationType.deduceFromClasspath() the method :
      • The purpose of this method is to infer the application type based on the classes that exist in the classpath.
      • It checks   the existence of classes like `<application>`  DispatcherHandlerDispatcherServlet` <script>`, and `<script>` to determine whether the application is a reactive, a standard Servlet web application, or  a non-web application. The most common Spring MVC application is   the `<application>` type.ServletREACTIVESERVLETNONESERVLET
  2. Execution  setInitializers method :
    • Function : Sets the application initializer ( ApplicationContextInitializer).
    • The most important part is  getSpringFactoriesInstances(ApplicationContextInitializer.class) the method :
      • The purpose of this method is to use Spring’s factory loading mechanism  META-INF/spring.factories to load and instantiate  ApplicationContextInitializer the implementation classes of all configurations from the configuration file.
      • Common initializers include those  ConfigurationWarningsApplicationContextInitializerfor checking configuration warnings and ContextIdApplicationContextInitializersetting the context ID. These initializers are  ApplicationContext called before a refresh.
  3. Execution  setListeners method :
    • Function : Set the application listener ( ApplicationListener).
    • The most important part is also  getSpringFactoriesInstances(ApplicationListener.class) the method :
      • The purpose of this method isspring.factories to load and instantiate all configurations  from it   ApplicationListener.
      • These listeners are used to listen for various events published during application startup, such as   ` ApplicationStartedEventclear cache` and `check file encoding`.ApplicationReadyEventClearCachesApplicationListenerFileEncodingApplicationListener
  4. Execution  deduceMainApplicationClass method :
    • Purpose : To deduce the main application class (i.e., the class in which we wrote  main the methods).
    • The principle is : traverse the current call stack and find the first  main class whose method name is [name missing].

At this point, SpringApplication the object has been constructed, and its initializer and listener are ready.


Phase Two: Execution  run Method

Execution method:SpringApplication.run(primarySources, args)

This is the most crucial and complex method in the entire startup process.

  1. Execute  getRunListeners and call the method listeners.starting() :
    • Function : To retrieve  SpringApplicationRunListeners and publish  ApplicationStartingEvent events.
    • Note : SpringApplicationRunListeners This is  SpringApplicationRunListener a collection specifically designed to listen   for key moments in the execution of methods. The first step is to publish events indicating that the application SpringApplication is  starting up .run
  2. Execution  prepareEnvironment method :
    • Function : To prepare and apply the environment ( Environment), which is the foundation of the entire application configuration.
    • The most important part is :
      • getOrCreateEnvironment()Create  StandardEnvironment or  based on application type StandardServletEnvironment.
      • configureEnvironment(environment, args): Configure the environment, including  PropertySources(property sources, such as JVM system properties, operating system environment variables) and  Profiles(configuration files, such as “dev”, “prod”).
      • listeners.environmentPrepared(environment): Publish  ApplicationEnvironmentPreparedEvent the event. This is an extremely important extension point . The listener for this event (most notably  ConfigFileApplicationListener) will   load our custom configuration properties from files such as application.properties.application.yml
  3. Execution  printBanner method :
    • Function : Prints the Spring Boot banner to the console.
  4. Execution  createApplicationContext method :
    • Function : Creates  ApplicationContext(IoC container).
    • Based on the deduction made in the first step WebApplicationType , different types of contexts are created. For Servlet web applications, this will be done  AnnotationConfigServletWebServerApplicationContext.
  5. Execution  prepareContext method :
    • Function : To prepare the data created above  ApplicationContext.
    • The most important part is :
      • postProcessApplicationContext(context)Post-processing application context, such as setting up bean name generators and resource loaders.
      • applyInitializers(context)Application initializerApplicationContextInitializer . Calls  all  methods loaded in the first step  initialize , allowing us to customize the context before the container is refreshed.
      • listeners.contextPrepared(context): Publish  ApplicationContextInitializedEvent an event to notify the listener that the context is ready.
      • load(context, sources.toArray(new Object[0]))Load the main source (i.e., our  @SpringBootApplication annotation class) into the context to prepare for subsequent component scanning and bean definition registration.
      • listeners.contextLoaded(context): Publish  ApplicationPreparedEvent an event to notify the listener that the context has been loaded.

Phase 3: Refreshing the application context

Execution method:refreshContext(context)

This method is called internally  AbstractApplicationContext.refresh(), which is the standard process for initializing the Spring framework container.

  1. Execution  prepareRefresh() method :
    • Purpose : Preparatory work before refreshing, such as initializing the property source and validating necessary properties.
  2. Execution  obtainFreshBeanFactory() method :
    • Function : To retrieve or refresh internal  BeanFactoryDefaultListableBeanFactory). BeanFactory It is the foundation of the Spring container.
  3. Execution  prepareBeanFactory(beanFactory) method :
    • Function : To prepare  BeanFactoryand configure its standard configuration, such as class loader and post-processor.
  4. Execution  postProcessBeanFactory(beanFactory) method :
    • Purpose : Allows post-processing after the Bean definition has been loaded but before instantiation  BeanFactory . This is an empty method for subclasses to extend.
  5. Execution  invokeBeanFactoryPostProcessors(beanFactory) method :
    • Purpose : This is the magic entry point for Spring Boot auto-configuration!
    • The most important part is : calling all  BeanFactoryPostProcessor.
    • Among them, ConfigurationClassPostProcessor it parses  @Configuration the classes that contain annotations. It will find the annotations on our main class  @SpringBootApplication .
    • @SpringBootApplication It is included in  @EnableAutoConfiguration, and the latter will be imported  AutoConfigurationImportSelector.
    • AutoConfigurationImportSelector It META-INF/spring.factories will  load the auto-configuration classes (e.g. ,  ) EnableAutoConfiguration corresponding to all keys  .DataSourceAutoConfigurationWebMvcAutoConfiguration
    • These auto-configuration classes determine whether to take effect based on conditions (such as whether a class exists in the classpath, whether a property is set, etc.) and add Bean definitions to the container in batches.
  6. Execution  registerBeanPostProcessors(beanFactory) method :
    • Function : Registration  BeanPostProcessor. These processors are  called after the bean is instantiated and before and after initialization  to enhance the bean (e.g.  @Autowired,  @PostConstruct features such as [list of features] are implemented through  BeanPostProcessor [the process]).
  7. Execution  initMessageSource() method :
    • Function : Initializes internationalization-related message sources.
  8. Execution  initApplicationEventMulticaster() method :
    • Function : Initializes the application event broadcaster for event publishing.
  9. Execution  onRefresh() method :
    • Purpose : This is a crucial step in Spring Boot creating and starting an embedded web server!
    • In  ServletWebServerApplicationContext [the original text], this method was rewritten.
    • The most important part is  createWebServer() the method :
      • The purpose of this method is to obtain (e.g.  ) BeanFactory from it   .ServletWebServerFactoryTomcatServletWebServerFactory
      • Calling  this factory.getWebServer(...) method creates an embedded Tomcat/Jetty/Undertow server instance and initializes the Servlet container (initializing  DispatcherServlet and registering it with the container) . At this point, the web server is created, but it has not yet started listening on the port.
  10. Execution  registerListeners() method :
    • Function : Register the listener, registering the event listener to the event broadcaster initialized in step 8.
  11. Execution  finishBeanFactoryInitialization(beanFactory) method :
    • Purpose : Complete  BeanFactory initialization, instantiating all remaining non-lazy-loaded singleton beans.
    • This is the main phase in which dependency injection occurs within the IoC container. Our Controller, Service, Repository, and other components are created and assembled during this phase.
  12. Execution  finishRefresh() method :
    • Function : To refresh the context and publish the final event.
    • The most important part is :
      • publishEvent(new ContextRefreshedEvent(this)): Publish  ContextRefreshedEvent the event.
      • ServletWebServerApplicationContext The process also involves calling  finishRefresh() an extension, which ultimately starts the embedded web server (for example  ) and begins listening on the specified port. At  TomcatWebServer.start()this point, our application can handle HTTP requests.

Phase 4: Post-startup processing

  1. Execution  afterRefresh(context, applicationArguments) method :
    • Function : Post-refresh processing; defaults to empty. It is an extension point.
  2. Execution  listeners.started(context) method :
    • Function : Publishes  ApplicationStartedEvent an event to notify all listeners that the application has started.
  3. Execution  callRunners(applicationArguments) method :
    • Function : To call  ApplicationRunner and  CommandLineRunner implement the interface.
    • This is a common way for developers to execute specific initialization logic after the application starts but before it begins receiving traffic.
  4. Execution  listeners.ready(context, timeTaken) method :
    • Purpose : Publish  ApplicationReadyEvent an event. This event signifies that the application has fully started and is in a ready state .  ApplicationStartedEvent The difference between this and [previous event name] is that at this point, all beans have been initialized and the embedded server is running.
  5. return ApplicationContext :
    • Function : Returns a fully initialized value  ApplicationContext .

Summarize

The entire process  main , starting with the method, involves  a series of complex and precise steps, including environment preparation, container creation, bean definition loading (auto-configuration), bean instantiation (dependency injection), embedded server startup, and running custom initialization logic  . Ultimately, a fully functional Spring Boot application is presented to us. The container  refreshContext() is the heart of the entire process, while auto-configuration and the embedded server are key to implementing Spring Boot’s two core features.