Understanding SpringBoot Startup: From main() to Web Container Initialization

This article walks through the complete SpringBoot startup sequence, starting with the main method annotated with @SpringBootApplication, detailing the creation of SpringApplication, environment preparation, context initialization, bean loading, embedded web server setup, event publishing, and final readiness, with code examples and common pitfalls.

Java Tech Workshop
Java Tech Workshop
Java Tech Workshop
Understanding SpringBoot Startup: From main() to Web Container Initialization

1. Startup Entry: main() Method

The entry point of a SpringBoot application is the main method in a class annotated with @SpringBootApplication. Although it looks like a single line of code, it triggers the entire startup process.

// Startup class
@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        // Core code: launch SpringBoot application
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

2. Core Entry: SpringApplication.run()

The whole startup flow begins with SpringApplication.run(). This method performs two core actions:

Create a SpringApplication instance, initializing core configuration such as application type detection, initializers, and listeners.

Invoke the overloaded run method to execute the detailed startup steps (environment preparation, context initialization, web container startup, etc.).

3. Source Code: SpringApplication Instance Creation

When SpringApplication.run() is called, the constructor of SpringApplication runs the following simplified logic:

public SpringApplication(Class<?>... primarySources) {
    this(null, primarySources);
}

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // Determine application type (WEB, REACTIVE, NONE)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // Load built‑in initializers
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // Load built‑in listeners
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // Deduce the main application class
    this.mainApplicationClass = deduceMainApplicationClass();
}

4. Core Startup Process (run method)

The run method (simplified) performs eight key steps, each corresponding to a specific operation and event:

Start timer and publish ApplicationStartingEvent – the earliest event, before any context or environment is created.

Prepare environment – create an Environment object, load configuration sources (system properties, command‑line args, application.properties/yml, profiles), then publish ApplicationEnvironmentPreparedEvent.

Print banner – optional; can be disabled with spring.banner.enabled=false or customized via banner.txt.

Create and initialize ApplicationContext – choose the concrete context class based on the application type (e.g., AnnotationConfigServletWebServerApplicationContext for servlet apps) and inject environment, initializers, and listeners. After initialization, publish ApplicationContextInitializedEvent.

Refresh the context – scan for bean definitions ( @Component, @Service, etc.), instantiate non‑lazy beans, perform dependency injection, execute @PostConstruct methods, and initialize built‑in features (AOP, transaction management). Finally, publish ContextRefreshedEvent.

Start the web container – if the type is SERVLET or REACTIVE, obtain a ServletWebServerFactory (default TomcatServletWebServerFactory), create the container, configure parameters (port, context path), register DispatcherServlet, start the server, and publish ServletWebServerInitializedEvent.

Execute custom runners – beans implementing CommandLineRunner or ApplicationRunner run after the context is ready. CommandLineRunner receives raw String[] args, while ApplicationRunner receives an ApplicationArguments object for easier option handling.

Publish final events – ApplicationStartedEvent (all beans initialized, web server started) and ApplicationReadyEvent (application fully ready to accept requests). The timer stops and startup duration is logged.

5. Web Container Initialization (Tomcat Example)

For servlet applications, the embedded Tomcat container is created and started as follows:

Create Tomcat instance via TomcatServletWebServerFactory.

Configure the connector (default port 8080, configurable via server.port and server.tomcat.connector.*).

Create TomcatWebApplicationContext to link Spring's context with Tomcat.

Register DispatcherServlet with the container (default mapping "/").

Start Tomcat by calling start(), which binds the connector to the port and begins listening for HTTP requests.

Publish ServletWebServerInitializedEvent after successful startup.

private void finishRefresh() {
    initLifecycleProcessor();
    getLifecycleProcessor().onRefresh();
    publishEvent(new ContextRefreshedEvent(this));
    WebServer webServer = startWebServer();
    if (webServer != null) {
        publishEvent(new ServletWebServerInitializedEvent(webServer, this));
    }
}

6. Common Configuration and Failure Scenarios

Embedded container – SpringBoot embeds Tomcat, Jetty, or Undertow, eliminating the need for external deployment.

Port configuration – default 8080; can be changed with server.port. If the port is occupied, a BindException is thrown.

Container switching – exclude Tomcat and add Jetty or Undertow dependencies to replace the default container.

Typical startup failures – port conflict, SSL misconfiguration, dependency conflicts (e.g., both Tomcat and Jetty on the classpath), illegal port numbers.

7. Event‑Driven Mechanism

The startup process is driven by a series of internal events published in a fixed order:

ApplicationStartingEvent
ApplicationEnvironmentPreparedEvent
ApplicationContextInitializedEvent
ContextRefreshedEvent
ServletWebServerInitializedEvent
ApplicationStartedEvent
ApplicationReadyEvent

8. Auto‑Configuration

Most of the above steps are automatically configured via @EnableAutoConfiguration, which is included in @SpringBootApplication. Spring scans

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

to load classes such as ServletWebServerFactoryAutoConfiguration and WebMvcAutoConfiguration.

9. Application Context Layers

BootstrapContext – loads early configuration (e.g., external config server, encryption) before the main ApplicationContext.

ApplicationContext – the primary context that manages all beans, dependency injection, and event publishing during the application lifecycle.

Mastering this flow enables rapid diagnosis of startup errors (e.g., bean‑creation failures, environment loading issues) and prepares you for interview questions about SpringBoot's internal mechanics.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

SpringBootStartupEventDrivenSpringApplicationEmbeddedTomcatWebContainer
Java Tech Workshop
Written by

Java Tech Workshop

Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.