Spring Boot启动过程全面解析:从入门到精通
wptr33 2025-06-10 02:11 1 浏览
一、Spring Boot概述
Spring Boot是一个基于Spring框架的快速开发脚手架,它通过"约定优于配置"的原则简化了Spring应用的初始搭建和开发过程。
1.1 Spring Boot核心特性
特性 | 说明 | 生活化比喻 |
自动配置 | 根据依赖自动配置Spring应用 | 像智能家居系统,检测到新设备自动配置 |
起步依赖 | 简化依赖管理,传递性依赖自动处理 | 像套餐服务,点一个主菜自动配好辅料 |
命令行界面 | 支持Groovy脚本和命令行交互 | 像智能语音助手,通过命令控制应用 |
Actuator | 提供生产级监控和管理功能 | 像汽车仪表盘,实时显示运行状态 |
1.2 Spring Boot vs Spring vs Spring MVC
维度 | Spring Boot | Spring | Spring MVC |
定位 | 快速开发脚手架 | 全栈框架 | Web框架 |
配置 | 自动配置为主 | 手动配置 | 手动配置 |
依赖管理 | 起步依赖简化 | 需手动管理 | 需手动管理 |
部署 | 内嵌服务器 | 需外部服务器 | 需外部服务器 |
适用场景 | 微服务、快速开发 | 需要高度定制 | 传统Web应用 |
二、Spring Boot启动过程深度解析
2.1 启动流程概览
2.2 详细启动步骤分析
步骤1:main方法入口
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
// 生活比喻:就像汽车的启动钥匙
SpringApplication.run(MyApplication.class, args);
}
}
步骤2:SpringApplication实例化
// SpringApplication构造方法核心代码分析
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断应用类型:Servlet、Reactive或None
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 初始化所有SpringBoot的初始化器(从META-INF/spring.factories加载)
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化所有SpringBoot的监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 推断主配置类(通过堆栈分析)
this.mainApplicationClass = deduceMainApplicationClass();
}
步骤3:运行SpringApplication
public ConfigurableApplicationContext run(String... args) {
// 1. 创建并启动计时器
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 准备环境
ConfigurableEnvironment environment = prepareEnvironment(...);
// 3. 打印Banner(就是启动时的Spring标志)
Banner printedBanner = printBanner(environment);
// 4. 创建应用上下文
context = createApplicationContext();
// 5. 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 6. 刷新上下文(核心步骤)
refreshContext(context);
// 7. 执行Runner(ApplicationRunner和CommandLineRunner)
callRunners(context, applicationArguments);
stopWatch.stop();
return context;
}
2.3 关键组件详解
2.3.1 自动配置原理
@Target(ElementType.TYPE) // 指定该注解只能应用于类、接口或枚举类型
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时保留,可通过反射获取
@Documented // 标记该注解应被包含在JavaDoc中
@Inherited // 标明该注解可被继承(子类会自动继承此注解)
@SpringBootConfiguration // 声明该类为Spring Boot配置类,底层继承自@Configuration
@EnableAutoConfiguration // 启用Spring Boot自动配置机制,根据依赖自动注册Bean
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), // 自定义过滤器,排除特定类型的组件
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) // 排除自动配置相关的类,避免重复注册
})
public @interface SpringBootApplication {
/**
* 配置属性:
* - exclude():指定需要排除的自动配置类
* - excludeName():通过类名排除自动配置类
* - proxyBeanMethods():控制@Bean方法是否代理(默认true)
*/
// 注解属性定义(示例):
// Class<?>[] exclude() default {};
// String[] excludeName() default {};
// boolean proxyBeanMethods() default true;
}
自动配置实现机制:
- @EnableAutoConfiguration 启用自动配置
- 从META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports加载配置类
- 通过@Conditional系列注解条件化加载Bean
生活化示例:就像智能家居系统,当你买回一台新电视:
- 系统检测到新设备(类似Spring检测到依赖)
- 自动配置电视的电源、网络等(自动配置Bean)
- 如果检测到你是VIP用户,还会自动开通高级频道(条件化配置)
2.3.2 内嵌服务器启动
Tomcat启动流程:
- 检测到spring-boot-starter-web依赖
- 自动配置ServletWebServerFactory
- 创建服务器实例并启动
// 简化的Tomcat启动代码
public class TomcatWebServer implements WebServer {
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
this.tomcat = tomcat;
initialize();
if (autoStart) {
start(); // 启动Tomcat
}
}
}
三、Spring Boot配置详解
3.1 配置文件类型对比
类型 | 文件格式 | 加载顺序 | 特点 | 适用场景 |
properties | key=value | 1 | 简单直观 | 简单配置、老项目兼容 |
yml | 层级结构 | 2 | 支持复杂结构 | 微服务、复杂配置 |
yaml | 同yml | 同yml | 同yml | 同yml |
3.2 常用配置项解析
application.yml示例:
# 服务器配置(好比餐厅的门面设置)
server:
port: 8080 # 营业窗口号
servlet:
context-path: /api # 餐厅入口路径
# 数据库配置(好比餐厅的食材仓库)
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: chef # 仓库管理员
password: secret # 仓库密码
driver-class-name: com.mysql.cj.jdbc.Driver
# 日志配置(好比餐厅的监控系统)
logging:
level:
root: info # 常规监控级别
org.springframework.web: debug # 特别关注区域
3.3 自定义配置与读取
方式1:@Value注解
@Component
public class Restaurant {
@Value("${restaurant.name}") // 读取配置项
private String name;
@Value("${restaurant.tables:10}") // 带默认值
private int tableCount;
}
方式2:@ConfigurationProperties
@ConfigurationProperties(prefix = "restaurant")
@Data // Lombok注解,自动生成getter/setter
public class RestaurantProperties {
private String name;
private String address;
private List<String> specialties;
private Map<String, Double> prices;
}
// 使用示例
@RestController
@EnableConfigurationProperties(RestaurantProperties.class)
public class MenuController {
@Autowired
private RestaurantProperties properties;
@GetMapping("/menu")
public String showMenu() {
return "今日特色菜: " + properties.getSpecialties();
}
}
四、Spring Boot高级特性
4.1 条件化装配详解
Spring Boot提供了丰富的条件注解:
注解 | 说明 | 生活化比喻 |
@ConditionalOnClass | 类路径存在指定类时生效 | 厨房有烤箱才提供烤制服务 |
@ConditionalOnMissingBean | 容器中没有指定Bean时生效 | 没有主厨时才启用备用厨师 |
@ConditionalOnProperty | 配置属性满足条件时生效 | 周末才开放自助餐服务 |
@ConditionalOnWebApplication | Web环境下生效 | 只有堂食才提供餐具 |
代码示例:
@Configuration
public class KitchenConfiguration {
// 只有当Oven类存在时才创建BakingService
@Bean
@ConditionalOnClass(name = "com.example.Oven")
public BakingService bakingService() {
return new BakingService();
}
// 只有配置了restaurant.feature.buffet=true时才启用
@Bean
@ConditionalOnProperty(prefix = "restaurant.feature", name = "buffet", havingValue = "true")
public BuffetService buffetService() {
return new BuffetService();
}
}
4.2 自定义Starter开发
开发一个简单的餐厅服务Starter:
- 创建自动配置类:
@Configuration
@ConditionalOnClass(RestaurantService.class)
@EnableConfigurationProperties(RestaurantProperties.class)
public class RestaurantAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RestaurantService restaurantService(RestaurantProperties properties) {
return new DefaultRestaurantService(properties);
}
}
- 创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件:
com.example.restaurant.autoconfigure.RestaurantAutoConfiguration
- 添加配置元数据(用于IDE提示):
// META-INF/spring-configuration-metadata.json
{
"properties": [
{
"name": "restaurant.name",
"type": "java.lang.String",
"description": "The name of the restaurant."
},
{
"name": "restaurant.tables",
"type": "java.lang.Integer",
"description": "Number of tables available.",
"defaultValue": 10
}
]
}
4.3 监控与管理(Actuator)
Actuator提供了一系列生产就绪特性:
常用端点:
端点 | 路径 | 描述 | 生活化比喻 |
health | /actuator/health | 应用健康状态 | 餐厅卫生检查 |
info | /actuator/info | 应用基本信息 | 餐厅招牌和简介 |
metrics | /actuator/metrics | 应用指标 | 餐厅经营数据报表 |
loggers | /actuator/loggers | 日志配置管理 | 餐厅监控系统设置 |
mappings | /actuator/mappings | URL映射 | 餐厅座位表 |
配置示例:
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: always
metrics:
enabled: true
五、Spring Boot启动优化
5.1 启动性能优化策略
策略 | 实现方式 | 效果 | 注意事项 |
延迟初始化 | spring.main.lazy-initialization=true | 减少启动时间 | 可能导致首次请求响应慢 |
排除自动配置 | @SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) | 减少不必要的配置 | 需确保不影响功能 |
组件扫描优化 | @ComponentScan(basePackages="com.myapp") | 减少扫描范围 | 不要漏掉必要组件 |
JVM参数调优 | -XX:TieredStopAtLevel=1 | 加快启动速度 | 影响峰值性能 |
5.2 类加载优化
Spring Boot 2.3+引入了分层JAR技术:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
分层结构:
- dependencies:依赖库
- spring-boot-loader:Spring Boot加载器
- snapshot-dependencies:快照依赖
- application:应用代码
六、常见问题与解决方案
6.1 启动问题排查表
问题现象 | 可能原因 | 解决方案 | 排查命令/工具 |
启动时报Bean创建失败 | 依赖缺失或配置错误 | 检查依赖和配置 | --debug模式启动 |
端口被占用 | 已有应用占用端口 | 更改端口或停止冲突应用 | netstat -ano |
自动配置不生效 | 条件不满足或扫描不到 | 检查@Conditional条件和组件扫描 | 启用自动配置报告(debug=true) |
启动慢 | 组件扫描范围大或依赖多 | 优化扫描范围,延迟初始化 | --trace模式启动 |
6.2 调试技巧
- 启用调试模式:
debug=true
- 查看自动配置报告: 报告会显示哪些自动配置类被应用/排除
- 使用启动监听器:
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
// 打印事件信息帮助调试
System.out.println("Received event: " + event.getClass().getSimpleName());
}
}
七、实战案例:餐厅管理系统
7.1 项目结构
restaurant-system
├── src/main/java
│ ├── com.example.restaurant
│ │ ├── config // 配置类
│ │ ├── controller // 控制器
│ │ ├── service // 服务层
│ │ ├── repository // 数据访问
│ │ └── model // 实体类
├── src/main/resources
│ ├── static // 静态资源
│ ├── templates // 模板文件
│ └── application.yml // 配置文件
7.2 核心代码实现
启动类:
@SpringBootApplication
public class RestaurantApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(RestaurantApplication.class);
// 添加初始化监听器
app.addListeners(new MyApplicationListener());
// 设置额外配置
app.setBannerMode(Banner.Mode.LOG);
app.run(args);
}
}
自定义Banner: 在src/main/resources下创建banner.txt:
____ _
| _ \ ___ ___ _ __ ___ _ __ | |_
| |_) / _ \/ __| '_ \ / _ \| '_ \| __|
| _ < __/\__ \ |_) | (_) | | | | |_
|_| \_\___||___/ .__/ \___/|_| |_|\__|
|_| v1.0.0
餐厅服务示例:
@Service
@Slf4j
public class RestaurantService implements ApplicationRunner {
@Autowired
private MenuService menuService;
@PostConstruct
public void init() {
log.info("餐厅准备营业...");
}
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("今日菜单已加载: {}", menuService.getTodaySpecial());
}
@PreDestroy
public void cleanup() {
log.info("餐厅打烊,清理中...");
}
}
八、Spring Boot启动过程总结
8.1 核心生命周期回调
阶段 | 回调方式 | 执行时机 | 典型用途 |
初始化 | @PostConstruct | Bean初始化完成后 | 资源加载、数据预热 |
启动后 | ApplicationRunner | 应用完全启动后 | 初始化业务数据 |
启动后 | CommandLineRunner | 同ApplicationRunner | 命令行参数处理 |
销毁前 | @PreDestroy | 应用关闭前 | 资源释放、数据保存 |
写结尾时才发现跑题了,但没关系,人生不也经常跑偏?
头条对markdown的文章显示不太友好,想了解更多的可以关注微信公众号:“Eric的技术杂货库”,后期会有更多的干货以及资料下载。
相关推荐
- flarum安装使用教程(flm安装教程安卓)
-
Flarum是一款现代化的、简洁美观的论坛软件,以下是关于它的环境安装:安装搭建基础环境:...
- 从abc起步学做网站(4)(从abc开始学英语用什么软件)
-
上一次我们做了一个大多数网站使用的模板,带有顶部、左侧导航、右侧主内容、底部等板块。现在我们把它逐步扩展成一个论坛。一个论坛的基本功能有注册,登陆,发帖,回帖,看帖,删帖等,我们一步步来做。首先大多数...
- 了解webshell变形的一些思路(webxshell)
-
请遵守法律法规,文章旨在提高安全软件的应变策略,严禁非法使用,后果自负。前言在攻防场景下,黑客常常在找到某个上传接口,第一步肯定是先测试后缀是否有限制,第二步则是测试上传的文件是否能解析,最后便确认即...
- MySQL8安装 八: 使用phpMyadmin客户端
-
MySQL8安装一:源码安装...
- PHP基本的语法、注释:让你的代码充满神秘色彩
-
PHP魔法咒语:让你的代码充满神秘色彩(带你进入PHP的魔法世界)一、笔记:基本的PHP语法PHP是一种超级强大的脚本语言,专为Web开发而设计。要想成为真正的PHP魔法师,首先需要掌握一些基本的语法...
- PHP——bc函数及其应用详解(php bcmul)
-
bcadd——两个任意精度数字的加法计算(PHP4,PHP5,PHP7,PHP8)...
- 从零学习php之php语法——课程1(php零基础自学)
-
以后将会每天更新一篇电脑编程教程有需要的朋友记得订阅转发哟怎么学习php?对于想学php还没入门的朋友很多都在纠结怎么开始第一步。我很了解php初学者的心理,因为我也是从那个阶段过来的,也是自学。那...
- 全新版Jetpack进阶提升,系统性落地短视频App|超清完结无秘
-
全新版Jetpack进阶提升,系统性落地短视频App|超清完结无秘来百度APP畅享高清图片...
- Reactive系统的反压(什么是反压)
-
原文BackpressureinReactiveSystemshttps://foojay.io/today/backpressure-in-reactive-systems/?spm=ata...
- Kotlin设计模式:Flyweight(享元)模式
-
享元模式的目的...
- 如何使用 Kotlin 在 Android 应用程序中使用 DataStore 首选项
-
在本教程中,我将向您展示如何使用数据存储首选项在Android应用程序中本地保存数据,而不是使用共享首选项的旧方法。我看到很多人不知道如何使用DataStore,他们认为这太难了,所以在这篇文章...
- Spring Native 中文文档(springdatajpa中文文档)
-
https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/#getting-started-buildpacks...
- 详解Android官推Kotlin-First的图片加载库
-
前言Coil是一个非常年轻的图片加载库,在2020年10月22日才发布了1.0.0版本,但却受到了Android官方的推广,在AndroidDevelopersBackst...
- Spring Boot通过@EnableCaching注解开启全局服务缓存功能!
-
Caching缓存缓存在现代应用中无处不在,它为服务的高可用提供了很大的帮助。Spring框架提供了对缓存的支持。SpringBoot通过@EnableCaching注解开启全局服务缓存功能。对于某...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)