Spring Boot Startup Explained: From Main Method to Tomcat Launch

This article walks through the complete Spring Boot startup sequence, starting with the SpringApplication.run entry point, detailing the preparation, application context creation, and refresh phases, and shows how the embedded Tomcat server is instantiated and started, illustrated with code snippets and diagrams.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Spring Boot Startup Explained: From Main Method to Tomcat Launch

Introduction

Recently a developer was asked in an interview about the Spring Boot startup process and when the embedded web container (Tomcat, Jetty, Undertow, etc.) is loaded and how the switch happens. This article answers those questions by tracing the execution from the SpringApplication.run(EasyPaasAdminApplication.class, args) entry point down to the point where Tomcat is started.

Execution Overview

Typical Spring Boot applications start with a static call to SpringApplication.run:

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

The run method creates a new SpringApplication instance, prepares the environment, creates the application context, refreshes it, and finally starts the embedded web server.

Static helper that can be used to run a SpringApplication from the specified source using default settings.

After this call the framework builds an ApplicationContext and, during the refresh phase, launches the web server.

Three Main Phases

Preparation phase, ApplicationContext creation phase, Refresh phase.

Preparation phase : Spring Boot loads initial settings and creates the SpringApplication context. The core code is the run() method of SpringApplication, which invokes various initializers.

ApplicationContext creation phase : Spring Boot builds the application context (either a WebApplicationContext for web apps or a generic ApplicationContext). Auto‑configuration scans the classpath, loads application.properties, application.yml, and META-INF/spring.factories, and registers beans.

Refresh phase : Spring Boot refreshes the context, creates the embedded web server, loads configuration, and initializes components. The Tomcat server is started during this phase.

Core Source Analysis

2.1 Preparation Phase

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    } catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        listeners.running(context);
    } catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

This method creates a StopWatch to measure startup time, obtains run listeners, prepares the environment, creates the application context, refreshes it, and finally registers shutdown hooks.

2.2 ApplicationContext Creation Phase

protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException("Unable to create a default ApplicationContext, please specify an ApplicationContextClass", ex);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

The method decides the concrete context class based on the application type (Servlet, Reactive, or none) and instantiates it.

2.3 Refresh Context Phase

protected void refreshContext(ConfigurableApplicationContext applicationContext) {
    refresh(applicationContext);
    if (this.registerShutdownHook) {
        try {
            applicationContext.registerShutdownHook();
        } catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}

The refresh call triggers the core ApplicationContext refresh, which starts the context, runs initializers, listeners, and ultimately creates the embedded WebServer (Tomcat by default).

During refresh Spring iterates over initializers and listeners:

for (ApplicationContextInitializer<?> initializer : getInitializers()) {
    initializer.initialize(applicationContext);
}
for (ApplicationListener<?> listener : getApplicationListeners()) {
    if (listener instanceof SmartApplicationListener) {
        SmartApplicationListener smart = (SmartApplicationListener) listener;
        if (smart.supportsEventType(eventType) && smart.supportsSourceType(sourceType)) {
            invokeListener(smart, event);
        }
    } else if (supportsEvent(listener, eventType)) {
        invokeListener(listener, event);
    }
}

These steps complete the startup and launch the embedded Tomcat server.

Reference

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.spring-application
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.

JavaBackend Developmentspring-bootEmbedded TomcatStartup Process
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

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.