Spring Boot is well-known for its ability to simplify the process of setting up and running a Spring-based application. One of the central features that makes this possible is the SpringApplication.run()
method. When you run a Spring Boot application, you often invoke this method as the entry point. However, have you ever wondered what actually happens behind the scenes?
In this blog, we’ll explore what occurs when SpringApplication.run()
is executed, diving into the process that eventually leads to the execution of the constructor you shared earlier. By understanding this, you’ll gain deeper insights into how Spring Boot starts up, configures itself, and prepares your application to run.
The Journey Begins: SpringApplication.run()
The SpringApplication.run()
method is the primary way to start a Spring Boot application. Here’s a simple example of its usage:
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
}
JavaWhen you call SpringApplication.run(MySpringBootApplication.class, args);
, several important steps take place to bootstrap your application.
Step 1: Creating the SpringApplication
Instance
The first thing SpringApplication.run()
does is create an instance of the SpringApplication
class. This is done through one of its static run
methods:
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
JavaThis line essentially calls the constructor of the SpringApplication
class:
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
JavaThis constructor is responsible for initializing the core components needed to start the Spring Boot application.
Step 2: Initializing the SpringApplication
Instance
The constructor you shared is then called:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
JavaLet’s break down what happens here:
- Resource Loader: If a custom
ResourceLoader
is provided, it’s set up here. If not, the default one is used. This handles how resources (like configuration files) are loaded in your application. - Primary Sources: The
primarySources
are the main configuration classes for your application, typically the class annotated with@SpringBootApplication
. - Web Application Type: Spring Boot determines if the application is a web application or a non-web application by checking the classpath. This influences the type of
ApplicationContext
that will be created. - Bootstrap Initializers: Instances of
BootstrapRegistryInitializer
are created. These are used during the early phase of the application’s lifecycle to customize the bootstrap process. - Application Context Initializers: These are configured to allow customization of the
ApplicationContext
before it is refreshed. - Application Listeners: Listeners for various application events are set up here. These can respond to events during startup, running, and shutdown.
- Main Application Class: The main application class is deduced, which is usually the class with the
main
method. This is important for logging and other contextual purposes.
Step 3: Running the Application
Once the SpringApplication
instance is fully initialized, the run()
method of this instance is called:
public ConfigurableApplicationContext run(String... args) {
...
}
JavaHere’s what happens during this run
method:
- Banner Display: The Spring Boot banner is displayed in the console, unless disabled.
- Environment Preparation: The environment is prepared, which includes loading properties from
application.properties
,application.yml
, system properties, environment variables, and command-line arguments. - Application Context Creation: Based on the application type (web or non-web), a suitable
ApplicationContext
is created. For web applications, aWebApplicationContext
is created. - Context Initialization: The previously set
ApplicationContextInitializers
are executed to customize the context before it is refreshed. - Application Listeners: The application listeners are called, handling various events like context start, stop, and refresh.
- Bean Creation and Dependency Injection: All beans defined in the application are created and dependencies are injected.
- Embedded Server Start (for Web Applications): If the application is a web application, the embedded server (like Tomcat or Jetty) is started.
- Runner Execution: Beans implementing
CommandLineRunner
orApplicationRunner
are executed to perform any task that needs to happen after the application is fully started.
Conclusion
The SpringApplication.run()
method is more than just a simple call to start your Spring Boot application. It orchestrates a series of well-defined steps, from setting up the environment and creating the application context, to starting the embedded server and executing custom runners.
Understanding what happens under the hood when you call SpringApplication.run()
provides valuable insights into the powerful abstractions Spring Boot offers, making it easier for developers to create robust and scalable applications with minimal configuration.
Whether you’re building a simple REST API or a complex microservices architecture, knowing how Spring Boot initializes your application can help you better manage your application’s lifecycle, troubleshoot issues, and optimize performance.