Day29 补一下Spring Boot

1. Spring Boot 概述

1.1 什么是 Spring Boot

Spring Boot 是基于 Spring 框架的开发框架,它通过”约定优于配置”的理念,简化了 Spring 应用的初始搭建和开发过程。Spring Boot 并不是对 Spring 功能的增强,而是提供了一种快速使用 Spring 的方式。

核心设计理念:

  • 约定优于配置:提供合理的默认值,减少手动配置
  • 开箱即用:集成常用第三方库的默认配置
  • 自动配置:根据类路径自动配置 Spring 应用

1.2 Spring Boot vs Spring Framework

特性Spring FrameworkSpring Boot
配置繁琐的 XML/Java 配置自动配置,约定优于配置
部署需要外置 Tomcat内嵌 Tomcat,直接运行
依赖手动管理版本冲突Starter 依赖管理,自动版本管理
开发效率较低,配置繁琐极高,快速启动
监控需要手动集成内置 Actuator 监控端点
生产支持需要额外配置内置生产级特性

1.3 Spring Boot 核心特性

mermaid
复制代码
graph TB A[Spring Boot] --> B[自动配置] A --> C[Starter 依赖] A --> D[内嵌服务器] A --> E[生产级特性] A --> F[无代码生成] A --> G[XML 配置可选] B --> B1[根据类路径自动配置] C --> C1[简化依赖管理] D --> D1[Tomcat/Jetty/Undertow] E --> E1[监控/健康检查/Metrics]

特性详解:

  1. 自动配置:Spring Boot 根据类路径中的依赖自动配置 Bean,大大减少了手动配置的工作量。
  2. Starter 依赖:提供了一系列开箱即用的依赖包,每个 Starter 都包含了一组相关的依赖和自动配置。
  3. 内嵌服务器:内嵌了 Tomcat、Jetty 或 Undertow,无需部署 WAR 包,直接运行 JAR 包。
  4. 生产级特性:内置了健康检查、指标监控、外部化配置等生产级特性。
  5. 无代码生成:Spring Boot 不会生成代码,而是通过字节码增强和动态代理实现功能。

核心原理

2.1 Spring Boot 启动流程

mermaid
复制代码
sequenceDiagram participant Main as main() participant SA as SpringApplication participant EP as Environment participant AC as ApplicationContext participant RC as RefreshContext Main->>SA: 创建 SpringApplication SA->>SA: 推断应用类型 SA->>SA: 加载 BootstrapRegister SA->>EP: 准备 Environment SA->>SA: 打印 Banner SA->>SA: 创建 ApplicationContext SA->>AC: 加载自动配置 SA->>AC: 刷新上下文 AC->>RC: 调用 refresh() RC->>RC: 扫描 Bean 定义 RC->>RC: 实例化 Bean RC->>RC: 执行后置处理器 SA->>Main: 启动完成

启动流程详细解析:

  1. 创建 SpringApplication:根据类路径推断应用类型(SERVLET、REACTIVE 等)
  2. 准备 Environment
    • 加载配置文件(application.yml/properties)
    • 加载系统属性和环境变量
    • 加载命令行参数
  3. 创建 ApplicationContext:根据应用类型创建合适的容器
  4. 刷新上下文
    • 执行 BeanFactoryPostProcessor
    • 注册 BeanPostProcessor
    • 实例化单例 Bean
  5. 启动应用:调用 CommandLineRunner 和 ApplicationRunner

2.2 @SpringBootApplication 注解

java
复制代码
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // 标识为配置类 @EnableAutoConfiguration // 启用自动配置 @ComponentScan( // 组件扫描 excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) } ) public @interface SpringBootApplication { // ... }

注解分解:

  1. @SpringBootConfiguration:本质上就是 @Configuration,标识这是一个配置类
  2. @EnableAutoConfiguration:开启自动配置,是 Spring Boot 的核心
  3. @ComponentScan:自动扫描当前包及其子包下的 @Component、@Service、@Repository 等

2.3 SpringApplication 核心方法

java
复制代码
public class SpringApplication { /** * 创建 SpringApplication 实例 */ public SpringApplication(Class<?>... primarySources) { this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.bootstrapRegistryInitializers = new ArrayList<>( getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners(getSpringFactoriesInstances(ApplicationListener.class)); } /** * 运行应用 */ public ConfigurableApplicationContext run(String... args) { long startTime = System.currentTimeMillis(); // 1. 创建 BootstrapContext DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // 2. 准备 Environment ConfigurableEnvironment environment = prepareEnvironment(bootstrapContext, args); // 3. 创建 ApplicationContext prepareContext(bootstrapContext, environment, args); // 4. 刷新上下文 context = refreshContext(context); // 5. 调用 Runner callRunners(context, args); return context; } }

3. 自动配置机制

3.1 自动配置原理

mermaid
复制代码
graph TD A[启动应用] --> B[加载主配置类] B --> C["@EnableAutoConfiguration"] C --> D[Import AutoConfigurationImportSelector] D --> E[读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports] E --> F[获取所有候选配置类] F --> G["@Conditional 注解过滤"] G --> H[过滤掉不符合条件的配置] H --> I[应用生效的配置] I --> J[注册到 Spring 容器]

自动配置原理详解:

Spring Boot 的自动配置通过以下步骤实现:

  1. @EnableAutoConfiguration 注解导入 AutoConfigurationImportSelector
  2. AutoConfigurationImportSelectorMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中读取所有自动配置类
  3. 对每个自动配置类,根据 @Conditional 系列注解进行过滤,只注册符合条件的 Bean
  4. 将过滤后的自动配置类注册到 Spring 容器

3.2 条件注解体系

注解说明应用场景
@ConditionalOnClass类路径中存在指定类检测是否引入了某个依赖
@ConditionalOnMissingClass类路径中不存在指定类避免与已有配置冲突
@ConditionalOnBean容器中存在指定 Bean依赖其他组件存在
@ConditionalOnMissingBean容器中不存在指定 Bean提供默认实现,允许覆盖
@ConditionalOnProperty配置文件中有指定属性根据配置开启/关闭功能
@ConditionalOnExpressionSpEL 表达式为 true复杂条件判断
@ConditionalOnWebApplicationWeb 应用环境仅在 Web 应用中生效
@ConditionalOnNotWebApplication非 Web 应用环境仅在非 Web 应用中生效
@ConditionalOnJava指定 Java 版本版本兼容性控制
@ConditionalOnResource资源存在检查配置文件是否存在

3.3 条件注解匹配原理

java
复制代码
/** * 条件注解的底层实现 */ public interface Condition { /** * 判断条件是否匹配 */ boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); } /** * 具体实现示例:@ConditionalOnClass */ class OnClassCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获取注解属性 List<String> onClasses = getClasses(metadata, "value"); List<String> onMissingClasses = getClasses(metadata, "missing"); // 检查类是否存在 boolean match = checkClasses(context.getClassLoader(), onClasses, true) && checkClasses(context.getClassLoader(), onMissingClasses, false); return match ? ConditionOutcome.match() : ConditionOutcome.noMatch("Required classes not found"); } }

3.4 自定义自动配置

java
复制代码
@Configuration @ConditionalOnClass(DataSource.class) @EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean public DataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl(properties.getUrl()); dataSource.setUsername(properties.getUsername()); dataSource.setPassword(properties.getPassword()); dataSource.setDriverClassName(properties.getDriverClassName()); return dataSource; } }

3.5 禁用自动配置

java
复制代码
@SpringBootApplication( exclude = {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class} ) public class DemoApplication { // ... }
yaml
复制代码
# application.yml 方式 spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

3.6 自动配置报告

启用自动配置报告,查看哪些配置生效/未生效:

yaml
复制代码
# application.yml debug:true

4. Starter 机制

4.1 Starter 原理

mermaid
复制代码
graph LR A[Starter 依赖] --> B[引入自动配置] A --> C[引入所需依赖] B --> D[自动配置类] B --> E[条件注解] C --> F[第三方库] C --> G[Spring 组件] D --> H[配置类注册] E --> I[按需生效]

Starter 设计原理:

  1. 依赖聚合:Starter 是一个空的 JAR 包,主要用于聚合相关依赖
  2. 自动配置:通过 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件注册自动配置类
  3. 条件装配:自动配置类通过 @Conditional 注解实现按需装配

命名规范:

  • 官方 Starter:spring-boot-starter-*
  • 第三方 Starter:*-spring-boot-starter

4.2 常用 Starter

Starter功能描述
spring-boot-starter-webWeb 应用开发,包含 Tomcat、Spring MVC
spring-boot-starter-data-jpaJPA 数据访问
spring-boot-starter-data-redisRedis 数据访问
spring-boot-starter-security安全认证
spring-boot-starter-aopAOP 面向切面编程
spring-boot-starter-test测试支持
spring-boot-starter-actuator监控和健康检查
spring-boot-starter-validation数据校验
mybatis-spring-boot-starterMyBatis 集成

4.3 自定义 Starter

目录结构

text
复制代码
my-spring-boot-starter/ ├── pom.xml ├── src/ │ └── main/ │ ├── java/ │ │ └── com/example/starter/ │ │ ├── MyStarterAutoConfiguration.java │ │ ├── MyStarterProperties.java │ │ └── MyService.java │ └── resources/ │ └── META-INF/ │ └── spring/ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

引入依赖文件

创建Maven项目,pom.xml里引入spring-boot-starter作为基础依赖

xml
复制代码
<project ...> <groupId>com.example</groupId> <artifactId>my-starter</artifactId> <version>1.0.0</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>

自动配置类

java
复制代码
@Configuration @EnableConfigurationProperties(MyStarterProperties.class) @ConditionalOnClass(MyService.class) @ConditionalOnProperty( prefix = "my.starter", name = "enabled", havingValue = "true", matchIfMissing = true ) public class MyStarterAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyStarterProperties properties) { return new MyService(properties); } }

属性配置类

java
复制代码
@ConfigurationProperties(prefix = "my.starter") @Data public class MyStarterProperties { private String name = "default"; private Integer maxRetries = 3; private Boolean enabled = true; }

注册文件

text
复制代码
com.example.starter.MyStarterAutoConfiguration

5. 配置管理

5.1 配置文件优先级

mermaid
复制代码
graph TD A[配置优先级] --> B[命令行参数] A --> C[操作系统环境变量] A --> D[Java 系统属性] A --> E[JAR 外部配置文件] A --> F[JAR 内部配置文件] A --> G["@PropertySource 注解"] A --> H[默认配置] B --> I[优先级最高] H --> J[优先级最低]

配置加载顺序(从高到低):

  1. 命令行参数
  2. 操作系统环境变量
  3. Java 系统属性
  4. JAR 外部配置文件
  5. JAR 内部配置文件
  6. @PropertySource 注解指定的配置文件
  7. 默认属性

5.2 配置文件格式

yaml
复制代码
# application.yml server: port:8080 servlet: context-path: /api spring: application: name: demo-application profiles: active: dev # 自定义配置 app: name: Demo App description: Spring Boot Demo config: timeout:3000 retry: max:3 delay:1000

5.3 多环境配置

text
复制代码
src/main/resources/ ├── application.yml # 默认配置 ├── application-dev.yml # 开发环境 ├── application-test.yml # 测试环境 └── application-prod.yml # 生产环境
yaml
复制代码
# application.yml spring: profiles: active: ${ENV:dev} # 默认 dev,可通过环境变量覆盖

5.4 配置属性绑定

java
复制代码
/** * 方式1: @ConfigurationProperties * 适用场景:复杂配置,多级属性 */ @Component @ConfigurationProperties(prefix = "app") @Data @Validated public class AppConfig { @NotBlank(message = "应用名称不能为空") private String name; private String description; @Valid private Config config = new Config(); @Data public static class Config { @Min(value = 100, message = "超时时间至少100ms") private Integer timeout; @Valid private Retry retry = new Retry(); @Data public static class Retry { @Min(value = 1, message = "最大重试次数至少1次") @Max(value = 10, message = "最大重试次数不超过10次") private Integer max; private Long delay; } } }

5.5 配置加密

xml
复制代码
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.5</version> </dependency>
yml
复制代码
jasypt: encryptor: password: ${JASYPT_PASSWORD} # 从环境变量获取 algorithm: PBEWithMD5AndDES app: password: ENC(加密后的密码)
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP