SpringBoot启动项目详解

发布于:2025-08-03 ⋅ 阅读:(14) ⋅ 点赞:(0)

SpringBoot 的启动过程是一个整合 Spring 核心容器、自动配置、嵌入式服务器等功能的复杂流程,核心目标是 “简化配置、快速启动”。下面从入口类开始,逐步拆解其详细启动步骤:

一、启动入口:@SpringBootApplicationmain方法

SpringBoot 应用的启动入口是一个带有@SpringBootApplication注解的类,其中的main方法是程序的起点:

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        // 核心启动方法
        SpringApplication.run(MyApplication.class, args);
    }
}

这行代码看似简单,却包含了初始化 Spring 容器、触发自动配置、启动嵌入式服务器等一系列操作。

二、@SpringBootApplication注解的核心作用

@SpringBootApplication是一个 “复合注解”,它整合了三个关键注解,为启动过程奠定基础:

  1. @SpringBootConfiguration:本质是@Configuration,标识当前类是一个配置类,允许通过@Bean定义 Bean。
  2. @ComponentScan:自动扫描当前类所在包及其子包下的@Component(包括@Service@Controller等)注解类,将其注册为 Spring Bean。
  3. @EnableAutoConfiguration:SpringBoot 的 “灵魂”,开启自动配置功能,通过加载预设的配置类,自动配置 DataSource、Web 服务器等组件。

三、SpringApplication.run()的详细流程

SpringApplication.run(MyApplication.class, args)是启动的核心方法,可拆解为两大阶段SpringApplication实例初始化 + run()方法执行。

阶段 1:SpringApplication实例初始化(准备工作)

当调用SpringApplication.run(...)时,首先会创建SpringApplication实例,完成一系列初始化操作:

// 简化的初始化逻辑
public SpringApplication(Class<?>... primarySources) {
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 1. 推断应用类型(Servlet/Reactive/Native)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 2. 加载初始化器(ApplicationContextInitializer)
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 3. 加载监听器(ApplicationListener)
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 4. 推断main方法所在的主类
    this.mainApplicationClass = deduceMainApplicationClass();
}

关键操作解析:

  • 推断应用类型:通过类路径中是否存在ServletReactive相关类,判断是传统 Web 应用(SERVLET)、响应式 Web 应用(REACTIVE)还是非 Web 应用(NONE)。
  • 加载初始化器:从META-INF/spring.factories文件中读取ApplicationContextInitializer实现类(用于初始化 Spring 上下文)。
  • 加载监听器:同样从spring.factories中读取ApplicationListener实现类(用于监听启动过程中的事件,如环境准备完成、容器刷新等)。
阶段 2:run()方法执行(核心启动流程)

run()方法是启动的核心,包含 12 个关键步骤,按顺序执行如下:

步骤 1:启动计时器(记录启动时间)
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 开始计时

用于统计应用启动总耗时,最终会在控制台输出(如Started MyApplication in 2.345 seconds)。

步骤 2:初始化运行监听器(SpringApplicationRunListeners

通过SpringFactoriesLoader加载SpringApplicationRunListener实现类(默认是EventPublishingRunListener),用于在启动各阶段发布事件(如ApplicationStartingEventApplicationEnvironmentPreparedEvent等),触发对应监听器的逻辑。

步骤 3:准备环境(Environment

创建并配置Environment(环境对象),包含:

  • 系统环境变量、JVM 参数、命令行参数(args)。
  • 配置文件(application.properties/application.yml)中的属性。
  • 激活的profiles(如dev/test/prod)。

过程:

  1. 为不同应用类型(Servlet/Reactive)创建对应Environment实例(如StandardServletEnvironment)。
  2. 加载配置文件:默认从classpath:classpath:/config/file:./file:./config/等路径读取。
  3. 处理命令行参数:将args中的参数(如--server.port=8081)添加到环境中,优先级最高。
步骤 4:打印 Banner(启动图标)

默认会在控制台打印 SpringBoot 的 Banner 图标(可通过spring.banner.location自定义,或设置spring.main.banner-mode=off关闭)。

步骤 5:创建ApplicationContext(Spring 容器)

根据应用类型创建对应的ApplicationContext(Spring 核心容器):

  • Servlet 应用AnnotationConfigServletWebServerApplicationContext
  • Reactive 应用AnnotationConfigReactiveWebServerApplicationContext
  • 非 Web 应用AnnotationConfigApplicationContext

ApplicationContext是 Spring 的 “大脑”,负责管理 Bean 的生命周期、依赖注入等核心功能。

步骤 6:准备ApplicationContext(上下文预处理)

为容器设置环境、注册 Bean、应用初始化器等:

  1. 将步骤 3 中准备好的Environment设置到容器中。
  2. 调用所有ApplicationContextInitializerinitialize()方法,对容器进行自定义初始化(如添加属性源、修改配置等)。
  3. 发布ApplicationContextInitializedEvent事件,通知监听器容器已初始化。
  4. 注册主配置类:将@SpringBootApplication标注的类(如MyApplication)注册为 Spring 的配置类。
步骤 7:刷新ApplicationContext(容器核心初始化)

这是 Spring 容器的核心步骤(继承自 Spring 的AbstractApplicationContext),包含 Bean 的扫描、加载、实例化等关键操作,具体包括:

7.1 执行BeanFactory的前置处理

初始化容器的BeanFactory(如DefaultListableBeanFactory),用于管理 BeanDefinition(Bean 的元数据)。

7.2 执行BeanFactoryPostProcessor(Bean 工厂后置处理器)

最关键的是自动配置类的加载
@EnableAutoConfiguration通过@Import(AutoConfigurationImportSelector.class)导入自动配置类。AutoConfigurationImportSelector会从META-INF/spring.factories中读取EnableAutoConfiguration对应的配置类(如DataSourceAutoConfigurationWebMvcAutoConfiguration等),并根据@Conditional条件注解(如@ConditionalOnClass@ConditionalOnMissingBean)筛选出符合当前环境的配置类,注册为 BeanDefinition。

7.3 注册BeanPostProcessor(Bean 后置处理器)

用于在 Bean 实例化前后进行增强(如 AOP 代理、依赖注入等)。

7.4 初始化消息源(国际化支持)
7.5 初始化事件多播器(用于事件发布)
7.6 初始化容器特定 Bean(子类扩展点)

对 Web 应用而言,这里会触发嵌入式服务器的创建与启动
ServletWebServerApplicationContextonRefresh()方法中调用createWebServer(),根据类路径中的依赖(如spring-boot-starter-tomcat)创建对应的服务器(Tomcat/Undertow/Jetty),并绑定端口(默认 8080)。

7.7 注册监听器到容器
7.8 完成 BeanFactory 初始化(实例化所有非懒加载单例 Bean)

容器会遍历所有 BeanDefinition,实例化单例 Bean(@Lazy标注的除外),并执行依赖注入(@Autowired)、初始化方法(@PostConstructInitializingBean)等。

7.9 发布容器刷新完成事件(ContextRefreshedEvent
步骤 8:刷新后的操作
  • 清除缓存(如类加载缓存)。
  • 发布ApplicationStartedEvent事件(通知容器已刷新完成)。
步骤 9:执行Runner(自定义启动逻辑)

调用所有ApplicationRunnerCommandLineRunnerrun()方法,执行启动后的自定义逻辑(如加载初始数据、检查配置等):

  • ApplicationRunner:接收ApplicationArguments参数(解析后的命令行参数)。
  • CommandLineRunner:直接接收原始String[] args参数。
步骤 10:发布启动完成事件

发布ApplicationReadyEvent事件,通知应用已完全启动,可对外提供服务。

步骤 11:停止计时器
stopWatch.stop(); // 停止计时
步骤 12:输出启动日志

打印启动成功日志,包含总耗时、活跃 Profiles 等信息(如Started MyApplication in 2.345 seconds (JVM running for 3.123))。

四、核心机制总结

  1. 自动配置:通过@EnableAutoConfigurationspring.factories中的配置类,根据依赖和环境自动配置组件(如 DataSource、Web 服务器)。
  2. 嵌入式服务器:在容器刷新阶段自动创建并启动(如 Tomcat),无需手动部署到外部服务器。
  3. 事件驱动:通过SpringApplicationRunListenerApplicationListener在启动各阶段发布事件,支持扩展(如自定义监听器处理特定阶段逻辑)。
  4. 简化配置:默认扫描路径、默认配置文件、默认 Bean 注册,减少手动配置。

五、流程图总结

main() → SpringApplication实例化 → run()
  ↓
初始化监听器 → 准备环境(配置+参数) → 打印Banner → 创建ApplicationContext
  ↓
准备上下文(设置环境+注册配置类) → 刷新上下文(核心)
  ↓
  ├─ 加载自动配置类 → 注册BeanDefinition
  ├─ 实例化单例Bean → 依赖注入
  └─ 启动嵌入式服务器(如Tomcat)
  ↓
执行Runner → 发布启动完成事件 → 输出启动日志

通过这一系列流程,SpringBoot 实现了 “零配置(或极简配置)” 的快速启动,让开发者专注于业务逻辑而非框架配置。


网站公告

今日签到

点亮在社区的每一天
去签到