Spring Boot启动源码深度分析 —— 新手也能看懂的原理剖析

Spring Boot启动源码深度分析------ 新手也能看懂的原理剖析

一、从一个熟悉的场景开始

每个Spring Boot开发者都知道这样一段代码:

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

这简单的几行代码背后,Spring Boot到底做了哪些工作?今天我们就来揭开这个神秘面纱。

二、Spring Boot启动的"四大阶段"

我把Spring Boot的启动过程比喻为一家餐厅的开张流程:

阶段一:筹备阶段(SpringApplication初始化)

java 复制代码
// 相当于餐厅开业前的筹备工作
SpringApplication app = new SpringApplication(MyApplication.class);
app.run(args);

在构造方法中,Spring Boot做了三件重要事情:

  1. 判断餐厅类型:是中式餐厅(Web)、西式餐厅(Reactive)还是快餐店(None)
  2. 招聘团队 :从META-INF/spring.factories文件中加载初始化和监听器
  3. 确定老板:找出主配置类(就是我们的MyApplication.class)

阶段二:环境准备(环境设置)

就像餐厅开业前要准备厨具、食材一样,Spring Boot需要准备运行环境:

  • 读取application.properties/yml配置文件
  • 处理命令行参数
  • 准备日志系统
  • 设置Profiles(环境标识:dev/test/prod)

阶段三:餐厅装修(创建应用上下文)

根据餐厅类型(Web应用类型)创建不同的"餐厅布局":

  • Servlet Web应用:创建AnnotationConfigServletWebServerApplicationContext
  • Reactive Web应用:创建AnnotationConfigReactiveWebServerApplicationContext
  • 普通应用:创建AnnotationConfigApplicationContext

阶段四:开业运营(刷新上下文)

这是最核心的步骤,相当于餐厅正式开始营业:

java 复制代码
// 简化的刷新过程
public void refresh() {
    // 1. 准备厨房(BeanFactory)
    prepareBeanFactory(beanFactory);
    
    // 2. 聘请厨师(BeanPostProcessors)
    invokeBeanFactoryPostProcessors(beanFactory);
    
    // 3. 注册服务员(BeanPostProcessors)
    registerBeanPostProcessors(beanFactory);
    
    // 4. 准备菜单(初始化MessageSource)
    initMessageSource();
    
    // 5. 安装广播系统(事件广播器)
    initApplicationEventMulticaster();
    
    // 6. 布置包间(初始化特定上下文子类)
    onRefresh();
    
    // 7. 招聘迎宾(注册监听器)
    registerListeners();
    
    // 8. 完成所有准备工作(完成BeanFactory初始化)
    finishBeanFactoryInitialization(beanFactory);
    
    // 9. 开业大吉(完成刷新)
    finishRefresh();
}

三、自动配置:Spring Boot的"智能管家"

自动配置是Spring Boot最神奇的特性,它就像个智能管家,能自动帮你配置好各种设施。

实现原理:条件化配置

Spring Boot通过一系列@Conditional注解来实现智能配置:

java 复制代码
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(DataSource.class)
public class DataSourceAutoConfiguration {
    // 当类路径存在DataSource类且没有自定义DataSource时才生效
}

配置加载机制

Spring Boot从META-INF/spring.factories文件中加载所有自动配置类:

ini 复制代码
# 自动配置入口
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
...

四、启动过程详细分解

让我们用更直观的方式理解整个启动过程:

graph TD A[SpringApplication.run] --> B[初始化SpringApplication] B --> C[准备环境Environment] C --> D[创建应用上下文ApplicationContext] D --> E[准备上下文] E --> F[刷新上下文Refresh] F --> G[执行Runners] subgraph 刷新上下文细节 F1[准备BeanFactory] F2[执行BeanFactoryPostProcessors] F3[注册BeanPostProcessors] F4[初始化事件广播器] F5[注册监听器] F6[完成Bean初始化] F7[发布完成事件] end F --> F1 --> F2 --> F3 --> F4 --> F5 --> F6 --> F7

五、实际开发中的小技巧

了解了原理后,我们可以在实际开发中做一些优化:

1. 加快启动速度

java 复制代码
// 排除不需要的自动配置
@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    ValidationAutoConfiguration.class
})

2. 自定义启动过程

java 复制代码
// 自定义初始化器
public class MyInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext context) {
        System.out.println("自定义初始化逻辑");
    }
}

// 注册使用
new SpringApplication(MyApplication.class)
    .addInitializers(new MyInitializer())
    .run(args);

3. 启动后执行特定逻辑

java 复制代码
@Component
public class MyRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("应用启动完成后执行");
    }
}

六、总结

Spring Boot的启动过程就像一家餐厅的开业流程:

  1. 筹备阶段:确定餐厅类型,组建团队(初始化)
  2. 环境准备:准备厨具食材(配置加载)
  3. 场地装修:根据类型装修餐厅(创建上下文)
  4. 开业运营:聘请厨师、准备菜单、迎接客人(刷新上下文)
  5. 智能管理:自动配置就像智能管家,根据需要自动配置

通过这样的比喻,是不是对Spring Boot的启动原理有了更直观的理解呢?

记住,理解源码不是为了背诵,而是为了在遇到问题时能够快速定位,在需要优化时知道从何下手。希望这篇文章能帮助你在Spring Boot的学习之路上更进一步!

相关推荐
智码看视界23 分钟前
Day19 Spring Boot启动优化:启动时间从8秒降到2秒
java·spring boot·后端·启动优化
SQL-First布道者1 小时前
Spring JDBC Ultra 十边型战士
java·spring boot·后端·mysql·spring·mybatis
Dovis(誓平步青云)1 小时前
《精讲Spring Boot后端跑另一个端口:如何解决暴露服务器问题》
服务器·人工智能·spring boot·后端·生成对抗网络
西门吹-禅12 小时前
java springboot N+1问题
java·开发语言·spring boot
weixin_BYSJ198713 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
leoZ23114 小时前
Claude 驱动的全栈开发:Spring Boot + Vue 的 BS 架构实践
vue.js·spring boot·架构
shepherd11117 小时前
一次把 Spring MVC 文件上传参数“查没了”的排查:multipart、Filter 与 request body 的连环坑
java·spring boot·后端
宠友信息19 小时前
MySQL 租户数据隔离在即时通讯源码后端中的落地方式
java·数据库·spring boot·redis·websocket·mysql
宠友信息1 天前
内容社区源码多端数据协议与 Spring Boot 状态流转实现思路
java·spring boot·websocket·uni-app
JerrySir1 天前
`spring.threads.virtual.enabled=true`:用三类负载定位等待、争用与拒绝
java·spring boot