一、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 | 应用关闭前 | 资源释放、数据保存 |
写结尾时才发现跑题了,但没关系,人生不也经常跑偏?