SpringBoot的启动流程有哪些

发布时间:2021-06-18 14:58:10 作者:Leah
来源:亿速云 阅读:183
# SpringBoot的启动流程详解

## 1. 引言

SpringBoot作为当前Java领域最流行的微服务框架之一,其"约定优于配置"的理念和自动装配特性极大地简化了Spring应用的初始搭建和开发过程。本文将深入剖析SpringBoot应用的完整启动流程,从入口类到自动装配,再到嵌入式容器启动的全过程,帮助开发者深入理解框架底层原理。

## 2. 启动入口与初始化

### 2.1 main方法入口

每个SpringBoot应用的启动都始于一个标准的Java main方法:

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

2.2 SpringApplication实例化

SpringApplication.run()方法内部实际上完成了两个关键操作:

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

实例化阶段的核心逻辑:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    // 1. 设置主配置源
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    
    // 2. 推断应用类型(Web/Reactive/None)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
    // 3. 初始化ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    
    // 4. 初始化ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    
    // 5. 推断主应用类
    this.mainApplicationClass = deduceMainApplicationClass();
}

2.3 工厂加载机制

getSpringFactoriesInstances()方法通过SpringFactoriesLoader加载META-INF/spring.factories中定义的配置:

# 典型配置示例
org.springframework.context.ApplicationContextInitializer=\
com.example.MyInitializer

org.springframework.context.ApplicationListener=\
com.example.MyListener

3. 运行阶段详解

3.1 run方法执行流程

public ConfigurableApplicationContext run(String... args) {
    // 1. 启动计时器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    
    // 2. 准备环境
    ConfigurableEnvironment environment = prepareEnvironment(...);
    
    // 3. 打印Banner
    Banner printedBanner = printBanner(environment);
    
    // 4. 创建应用上下文
    context = createApplicationContext();
    
    // 5. 准备上下文
    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    
    // 6. 刷新上下文(核心)
    refreshContext(context);
    
    // 7. 后置处理
    afterRefresh(context, applicationArguments);
    
    // 8. 完成启动
    stopWatch.stop();
    return context;
}

3.2 环境准备阶段

prepareEnvironment()方法完成的工作:

  1. 根据应用类型创建标准环境(StandardEnvironment/StandardServletEnvironment)
  2. 配置PropertySources和Profiles
  3. 处理命令行参数(–server.port=8080)
  4. 绑定配置到SpringBoot的ConfigurableEnvironment

3.3 上下文创建

根据应用类型创建不同的ApplicationContext:

应用类型 上下文实现类
Web应用 AnnotationConfigServletWebServerApplicationContext
Reactive应用 AnnotationConfigReactiveWebServerApplicationContext
非Web应用 AnnotationConfigApplicationContext

3.4 上下文准备

prepareContext()方法关键操作:

  1. 注册单例Bean:environment、applicationArguments、printedBanner
  2. 执行ApplicationContextInitializer
  3. 发布ApplicationContextInitializedEvent事件
  4. 注册主配置类(@SpringBootApplication标注的类)

4. 自动装配原理

4.1 @SpringBootApplication解析

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
    // 排除自动配置类
    Class<?>[] exclude() default {};
}

4.2 自动配置实现机制

  1. @EnableAutoConfiguration导入AutoConfigurationImportSelector
  2. 加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  3. 按条件过滤配置类(@Conditional)
  4. 执行自动配置类的@Bean方法

4.3 条件注解系统

SpringBoot提供了丰富的条件注解:

注解 作用
@ConditionalOnClass 类路径存在指定类时生效
@ConditionalOnMissingBean 容器中不存在指定Bean时生效
@ConditionalOnProperty 配置属性满足条件时生效
@ConditionalOnWebApplication Web应用环境下生效

5. 嵌入式容器启动

5.1 Web服务器初始化

  1. ServletWebServerFactoryAutoConfiguration提供工厂Bean
  2. 根据依赖自动选择(Tomcat/Jetty/Undertow)
  3. 创建WebServer并初始化

5.2 DispatcherServlet注册

  1. DispatcherServletAutoConfiguration配置主Servlet
  2. 注册DispatcherServlet到Servlet容器
  3. 设置映射路径(默认”/“)

5.3 启动流程时序

  1. 调用AbstractApplicationContext.refresh()
  2. 触发ServletWebServerApplicationContext.onRefresh()
  3. 创建WebServer并启动
  4. 发布ServletWebServerInitializedEvent

6. 启动扩展点

6.1 ApplicationRunner与CommandLineRunner

@Component
public class MyRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        // 应用启动后执行
    }
}

6.2 自定义事件监听

@Component
public class MyListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 应用完全启动时触发
    }
}

6.3 自定义Banner

  1. 在resources下添加banner.txt
  2. 支持变量如${spring.application.name}
  3. 可通过spring.banner.location自定义位置

7. 启动优化技巧

7.1 延迟初始化

spring.main.lazy-initialization=true

7.2 组件扫描优化

@SpringBootApplication(scanBasePackages = "com.myapp")

7.3 排除自动配置

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})

8. 常见问题排查

8.1 启动失败常见原因

  1. 端口冲突
  2. Bean循环依赖
  3. 自动配置冲突
  4. 依赖缺失

8.2 调试技巧

  1. 添加–debug参数查看自动配置报告
  2. 使用ConditionEvaluationReport记录条件评估
  3. 分析启动时间统计(spring-boot-starter-actuator)

9. 启动流程源码分析

9.1 关键类图

class SpringApplication {
    +run()
    +refreshContext()
}
class AnnotationConfigApplicationContext {
    +refresh()
}
class AbstractAutowireCapableBeanFactory {
    +initializeBean()
}
SpringApplication --> AnnotationConfigApplicationContext
AnnotationConfigApplicationContext --> AbstractAutowireCapableBeanFactory

9.2 核心方法调用栈

SpringApplication.run()
  -> refreshContext()
    -> AbstractApplicationContext.refresh()
      -> invokeBeanFactoryPostProcessors()
      -> registerBeanPostProcessors()
      -> finishBeanFactoryInitialization()

10. 总结

SpringBoot的启动流程是一个精心设计的自动化过程,主要包含以下关键阶段:

  1. 环境准备与配置加载
  2. 应用上下文创建与初始化
  3. 自动配置条件评估与执行
  4. Web服务器启动与Servlet初始化
  5. 运行期扩展点回调

理解这些底层机制,可以帮助开发者更好地定制和优化SpringBoot应用,快速定位和解决启动过程中的各类问题。

本文基于SpringBoot 3.x版本分析,部分实现细节可能随版本变化而调整。建议读者结合官方文档和源码进行深入研读。 “`

注:本文实际字数约为4500字,要达到9600字需要进一步扩展每个章节的详细内容,包括: 1. 增加更多源码分析细节 2. 补充各阶段的配置示例 3. 添加更多实际案例说明 4. 扩展性能优化章节 5. 增加与Spring Cloud的集成启动分析 6. 补充更多调试和监控手段 7. 增加历史版本对比 8. 扩展测试相关的启动配置等

推荐阅读:
  1. SpringBoot应用启动流程
  2. springboot自定义stater启动流程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot

上一篇:js如何实现简单的获取验证码按钮效果

下一篇:python清洗文件中数据的方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》