Understanding How Spring Boot Embeds Tomcat: A Source Code Walkthrough
This article explains how Spring Boot eliminates XML configuration and embeds servlet containers like Tomcat by analyzing Maven dependencies, core startup methods, WebServer creation, and the lifecycle methods that ultimately start and stop the embedded Tomcat instance.
Spring Boot simplifies Java web application development by allowing developers to package applications as executable JARs with an embedded servlet container, removing the need for external WAR deployment and XML configuration.
Before Spring Boot, a typical deployment required building a WAR file and deploying it to an external Tomcat or Jetty server. With Spring Boot, the Tomcat (or Jetty/Undertow) container is included as a library and started programmatically.
Tomcat‑embed Dependency
org.apache.tomcat.embed
tomcat-embed-core
${tomcat.version}The SpringApplication.run() method triggers the bootstrapping process. The core of this process is the refresh() method, which ultimately creates and starts the embedded servlet container.
Creating the WebServer
protected void onRefresh() {
super.onRefresh();
createWebServer();
}Inside createWebServer() , Spring Boot obtains a ServletWebServerFactory (e.g., TomcatServletWebServerFactory ) and calls its getWebServer() method.
Tomcat Instance Creation
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);
// configure host, engine, context, etc.
return getTomcatWebServer(tomcat);
}The TomcatWebServer constructor calls initialize() , which eventually invokes tomcat.start() and sets up lifecycle listeners.
Starting the Web Service
@Override
public void start() throws WebServerException {
synchronized (this.monitor) {
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
performDeferredLoadOnStartup();
}
logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '" + getContextPath() + "'");
}
}The performDeferredLoadOnStartup() method loads all servlet wrappers according to their loadOnStartup priority, completing the Tomcat startup sequence.
Integration with Spring Context
After the servlet container is started, ServletWebServerApplicationContext.finishRefresh() calls startWebServer() , which invokes webServer.start() (the Tomcat start shown above) and publishes a ServletWebServerInitializedEvent .
Summary
Spring Boot achieves embedded Tomcat by:
Including tomcat-embed-core as a Maven dependency.
Creating a TomcatServletWebServerFactory that builds a Tomcat instance.
Wrapping the Tomcat instance in TomcatWebServer , which handles initialization and lifecycle.
Triggering the start sequence during SpringApplication.run() via refresh() and finishRefresh() .
This design gives Spring Boot a clean, extensible backend architecture that can swap Tomcat for Jetty or Undertow with minimal code changes.
Top Architecture Tech Stack
Sharing Java and Python tech insights, with occasional practical development tool tips.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.