> 技术文档 > Spring Boot启动原理:从main方法到内嵌Tomcat的全过程

Spring Boot启动原理:从main方法到内嵌Tomcat的全过程

Spring Boot的启动过程是一个精心设计的自动化流程,下面我将详细阐述从main方法开始到内嵌Tomcat启动的全过程。

1. 入口:main方法

一切始于一个简单的main方法:

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

2. SpringApplication初始化

SpringApplication.run()方法内部会创建一个SpringApplication实例:

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return new SpringApplication(primarySource).run(args);}

2.1 构造阶段

在SpringApplication构造函数中完成以下关键操作:

  • 推断应用类型:判断是Servlet应用(Spring MVC)还是Reactive应用(Spring WebFlux)
  • 加载ApplicationContextInitializer:通过META-INF/spring.factories加载
  • 加载ApplicationListener:同样通过spring.factories机制加载
  • 推断主配置类:通过堆栈分析找到包含main方法的类

3. 运行阶段:run()方法

run()方法是整个启动过程的核心:

public ConfigurableApplicationContext run(String... args) { // 1. 创建并启动计时器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 2. 初始化应用上下文和异常报告器 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); // 3. 获取SpringApplicationRunListeners并启动 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { // 4. 准备环境 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 5. 打印Banner Banner printedBanner = printBanner(environment); // 6. 创建应用上下文 context = createApplicationContext(); // 7. 准备应用上下文 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 8. 刷新应用上下文(关键步骤) refreshContext(context); // 9. 刷新后处理 afterRefresh(context, applicationArguments); // 10. 停止计时器并发布启动完成事件 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); // 11. 执行Runner 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;}

4. 创建应用上下文

createApplicationContext()方法根据应用类型创建不同的应用上下文:

  • Servlet环境:创建AnnotationConfigServletWebServerApplicationContext
  • Reactive环境:创建AnnotationConfigReactiveWebServerApplicationContext
  • 普通环境:创建AnnotationConfigApplicationContext

对于Web应用,会创建AnnotationConfigServletWebServerApplicationContext,它继承自ServletWebServerApplicationContext

5. 准备应用上下文

prepareContext()方法完成以下工作:

  • 将环境绑定到上下文
  • 后置处理上下文
  • 应用所有初始化器
  • 发布ContextPrepared事件
  • 注册主配置类bean定义
  • 发布ContextLoaded事件

6. 刷新应用上下文

refreshContext()最终调用AbstractApplicationContext.refresh(),这是Spring容器的核心刷新流程:

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新 prepareRefresh(); // 2. 获取新的BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. 准备BeanFactory prepareBeanFactory(beanFactory); try { // 4. 后置处理BeanFactory postProcessBeanFactory(beanFactory); // 5. 调用BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册BeanPostProcessor registerBeanPostProcessors(beanFactory); // 7. 初始化MessageSource initMessageSource(); // 8. 初始化事件广播器 initApplicationEventMulticaster(); // 9. 初始化特殊bean(由子类实现) onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 初始化所有非懒加载单例 finishBeanFactoryInitialization(beanFactory); // 12. 完成刷新 finishRefresh(); } catch (BeansException ex) { // 处理异常... } }}

7. 内嵌Tomcat启动的关键:onRefresh()

对于Servlet Web应用,ServletWebServerApplicationContext重写了onRefresh()方法:

protected void onRefresh() { super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException(\"Unable to start web server\", ex); }}

createWebServer()是内嵌服务器启动的关键:

private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { // 1. 获取WebServer工厂(Tomcat, Jetty或Undertow) ServletWebServerFactory factory = getWebServerFactory(); // 2. 创建WebServer this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException(\"Cannot initialize servlet context\", ex); } } initPropertySources();}

8. Tomcat服务器创建过程

以Tomcat为例,TomcatServletWebServerFactory.getWebServer()方法:

public WebServer getWebServer(ServletContextInitializer... initializers) { // 1. 创建Tomcat实例 Tomcat tomcat = new Tomcat(); // 2. 配置基础目录 File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir(\"tomcat\"); tomcat.setBaseDir(baseDir.getAbsolutePath()); // 3. 配置连接器 Connector connector = new Connector(this.protocol); connector.setThrowOnFailure(true); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); // 4. 配置Host tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); // 5. 准备上下文 prepareContext(tomcat.getHost(), initializers); // 6. 创建TomcatWebServer并启动 return getTomcatWebServer(tomcat);}

9. 启动Tomcat

TomcatWebServer构造函数中完成Tomcat的启动:

public TomcatWebServer(Tomcat tomcat, boolean autoStart) { this.tomcat = tomcat; this.autoStart = autoStart; initialize();}private void initialize() throws WebServerException { // 启动Tomcat this.tomcat.start(); // 启动一个守护线程来等待停止命令 startDaemonAwaitThread();}

10. 自动配置的关键

整个过程中,自动配置是通过@SpringBootApplication注解中的@EnableAutoConfiguration实现的:

  • invokeBeanFactoryPostProcessors()阶段会处理自动配置
  • AutoConfigurationImportSelector会加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中的配置类
  • 对于Tomcat,会加载ServletWebServerFactoryAutoConfiguration
  • 这个配置类通过@Import引入了EmbeddedTomcat等配置

总结流程

  1. 启动main方法
  2. 创建SpringApplication实例
  3. 运行run()方法
  4. 准备环境
  5. 创建应用上下文(AnnotationConfigServletWebServerApplicationContext)
  6. 准备上下文(注册配置类等)
  7. 刷新上下文(核心)
    • 调用onRefresh()
    • 创建内嵌Web服务器(Tomcat)
    • 启动Tomcat
  8. 发布启动完成事件
  9. 执行Runner

🚀 欢迎关注:
关注底部微信公众号,可学习、源码及副业接单:
回复【进群】,免费进副业接单群!
回复【副业】,领取副业接单技巧及避坑指南!
回复【java】,领取2025年Java学习路线!

Spring Boot启动原理:从main方法到内嵌Tomcat的全过程