Backend Development 14 min read

How Spring Boot Boots Tomcat: Deep Dive into the Startup Process

This article explains how Spring Boot launches an embedded Tomcat server by tracing the main method, creating and refreshing the application context, and initializing Tomcat's core components such as connectors and containers, while detailing the hierarchy of Engine, Host, Context, and Wrapper.

macrozheng
macrozheng
macrozheng
How Spring Boot Boots Tomcat: Deep Dive into the Startup Process

Preface

Spring Boot offers a new development experience by allowing a web application to be packaged as a runnable JAR with an embedded container. This article uses Tomcat as an example to show how Spring Boot starts Tomcat and explores Tomcat's source code to understand its design.

Starting from the Main Method

Spring Boot applications begin with a

main

method that invokes

SpringApplication.run

.

<code>@SpringBootApplication
public class TomcatdebugApplication {
    public static void main(String[] args) {
        SpringApplication.run(TomcatdebugApplication.class, args);
    }
}
</code>

The

run

method creates a

ConfigurableApplicationContext

and performs a series of steps, including configuring properties, publishing start events, initializing arguments, preparing the environment, creating the context, refreshing it, and finally publishing the running events.

Configure properties Obtain listeners and publish the start event Initialize input arguments Prepare environment and print banner Create application context Pre‑process the context Refresh the context Refresh the context again (extension point) Publish the started event Publish the running event

For Tomcat, the crucial steps are the creation of the application context (

createApplicationContext()

) and its refresh (

refreshContext(context)

).

Creating the Application Context

<code>protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        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);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
</code>

The method selects the appropriate context class based on

webApplicationType

. For a typical Spring Boot web application, it instantiates

AnnotationConfigServletWebServerApplicationContext

, which extends

ServletWebServerApplicationContext

and ultimately

AbstractApplicationContext

.

Refreshing the Context

<code>private void refreshContext(ConfigurableApplicationContext context) {
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        } catch (AccessControlException ex) {
            // ignored in restricted environments
        }
    }
}

protected void refresh(ApplicationContext applicationContext) {
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
}
</code>

The

refresh

call ultimately invokes

AbstractApplicationContext.refresh()

, which prepares the context, loads bean definitions, registers post‑processors, initializes special beans, and finally publishes the

ContextRefreshedEvent

.

Tomcat Internals

During the refresh,

ServletWebServerApplicationContext.onRefresh()

creates the embedded web server. The

TomcatServletWebServerFactory.getWebServer()

method builds a

Tomcat

instance, configures a

Connector

, and sets up the engine hierarchy.

<code>@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
    Tomcat tomcat = new Tomcat();
    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    Connector connector = new Connector(this.protocol);
    tomcat.getService().addConnector(connector);
    tomcat.setConnector(connector);
    tomcat.getHost().setAutoDeploy(false);
    configureEngine(tomcat.getEngine());
    for (Connector additionalConnector : this.additionalTomcatConnectors) {
        tomcat.getService().addConnector(additionalConnector);
    }
    prepareContext(tomcat.getHost(), initializers);
    return getTomcatWebServer(tomcat);
}
</code>

The engine hierarchy consists of four container types:

Engine – the top‑level container.

Host – child of Engine, represents a virtual host.

Context – child of Host, corresponds to a servlet context (a web application).

Wrapper – child of Context, wraps an individual servlet.

Tomcat’s

Server

contains one or more

Service

objects; each Service holds an

Engine

and one or more

Connector

instances.

The diagram above shows the inheritance chain:

AnnotationConfigServletWebServerApplicationContext

ServletWebServerApplicationContext

AbstractApplicationContext

.

Summary

Spring Boot starts by creating a

SpringApplication

instance, which configures properties, publishes start events, prepares the environment, creates and refreshes the application context, and finally runs any

ApplicationRunner

or

CommandLineRunner

. The Tomcat startup occurs during the context refresh, where the embedded server is built, a

Connector

is added, and the container hierarchy (Engine → Host → Context → Wrapper) is initialized.

JavaSpring BootTomcatEmbedded ServerWeb Application Context
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login 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.