Skip to main content

Spring Boot 详解

Spring Boot是一个基于Spring框架的快速开发平台,它通过约定优于配置的理念,简化了Spring应用的配置和部署。Spring Boot提供了自动配置、内嵌服务器、生产就绪特性等,大大提高了开发效率。

1. Spring Boot基础概念

1.1 什么是Spring Boot?

Spring Boot是Spring框架的扩展,它简化了Spring应用的初始搭建和开发过程。通过自动配置、起步依赖、内嵌服务器等特性,让开发者能够快速构建生产就绪的Spring应用。

1.2 Spring Boot的核心特性

  • 自动配置:根据依赖自动配置应用
  • 起步依赖:简化Maven/Gradle依赖管理
  • 内嵌服务器:内置Tomcat、Jetty等服务器
  • 生产就绪:监控、健康检查等

2. 自动配置原理

Spring Boot的自动配置基于条件注解和Spring Factories机制,是其核心功能之一。

核心概念

🚀 自动配置:Spring Boot会根据添加的jar依赖自动配置Spring应用上下文,减少开发者手动配置的工作量。

2.1 自动配置流程

自动配置的基本流程如下:

  1. 应用启动时,通过@SpringBootApplication注解上的@EnableAutoConfiguration启用自动配置功能
  2. AutoConfigurationImportSelector读取所有依赖中的META-INF/spring.factories文件
  3. 收集所有org.springframework.boot.autoconfigure.EnableAutoConfiguration项下的配置类
  4. 根据条件注解(@ConditionalOnXXX)筛选出符合条件的配置类
  5. 创建并注册这些配置类中定义的Bean
Spring Boot主类
java
1@SpringBootApplication // 包含@EnableAutoConfiguration
2public class MyApplication {
3 public static void main(String[] args) {
4 SpringApplication.run(MyApplication.class, args);
5 }
6}

2.2 条件注解详解

条件注解是自动配置的核心机制,决定了配置是否应该被应用。

主要条件注解

条件注解描述示例
@ConditionalOnClass当指定类存在于类路径时@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingClass当指定类不存在于类路径时@ConditionalOnMissingClass("org.hibernate.Session")
@ConditionalOnBean当指定Bean存在于容器中时@ConditionalOnBean(name = "dataSource")
@ConditionalOnMissingBean当指定Bean不存在于容器中时@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty当配置属性满足条件时@ConditionalOnProperty(prefix = "app", name = "cache", havingValue = "true")
@ConditionalOnResource当指定资源存在时@ConditionalOnResource(resources = "classpath:config.properties")
@ConditionalOnWebApplication当应用是Web应用时@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnNotWebApplication当应用不是Web应用时@ConditionalOnNotWebApplication
@ConditionalOnExpression当SpEL表达式为true时@ConditionalOnExpression("'${spring.profiles.active}' == 'dev'")
条件注解使用示例
java
1@Configuration
2@ConditionalOnClass(DataSource.class) // 当类路径下有DataSource类时
3@ConditionalOnProperty(prefix = "spring.datasource", name = "url") // 当配置了spring.datasource.url属性时
4public class DataSourceAutoConfiguration {
5
6 @Bean
7 @ConditionalOnMissingBean // 当容器中不存在DataSource类型的Bean时
8 public DataSource dataSource() {
9 // 创建默认数据源
10 return DataSourceBuilder.create().build();
11 }
12
13 @Bean
14 @ConditionalOnProperty(prefix = "spring.datasource", name = "initialize", havingValue = "true", matchIfMissing = true)
15 public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
16 // 初始化数据源
17 return new DataSourceInitializer(dataSource);
18 }
19}

2.3 自动配置的实现原理

Spring Boot自动配置的核心实现基于@EnableAutoConfiguration注解和AutoConfigurationImportSelector选择器。

EnableAutoConfiguration源码
java
1@Target(ElementType.TYPE)
2@Retention(RetentionPolicy.RUNTIME)
3@Documented
4@Inherited
5@AutoConfigurationPackage
6@Import(AutoConfigurationImportSelector.class)
7public @interface EnableAutoConfiguration {
8
9 String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
10
11 // 排除特定的自动配置类
12 Class<?>[] exclude() default {};
13
14 // 按名称排除自动配置类
15 String[] excludeName() default {};
16}

@EnableAutoConfiguration注解通过@Import导入AutoConfigurationImportSelector,这个选择器负责加载和筛选自动配置类。

2.4 自定义自动配置

你可以创建自己的自动配置类,实现特定功能的自动配置。

自定义自动配置类示例
java
1// 步骤1:创建配置属性类
2@ConfigurationProperties(prefix = "acme")
3public class AcmeProperties {
4
5 private boolean enabled = false;
6 private String apiKey;
7 private List<String> allowedOrigins = new ArrayList<>();
8
9 // getter和setter
10}
11
12// 步骤2:创建自动配置类
13@Configuration
14@ConditionalOnClass(AcmeClient.class)
15@EnableConfigurationProperties(AcmeProperties.class)
16public class AcmeAutoConfiguration {
17
18 private final AcmeProperties properties;
19
20 public AcmeAutoConfiguration(AcmeProperties properties) {
21 this.properties = properties;
22 }
23
24 @Bean
25 @ConditionalOnMissingBean
26 @ConditionalOnProperty(prefix = "acme", name = "enabled", havingValue = "true")
27 public AcmeClient acmeClient() {
28 return new AcmeClient(properties.getApiKey(), properties.getAllowedOrigins());
29 }
30}
31
32// 步骤3:注册自动配置类(在META-INF/spring.factories文件中)
33// org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
34// com.example.AcmeAutoConfiguration
注意事项

创建自定义自动配置时,需要遵循以下原则:

  1. 尽量使用条件注解,避免强制用户使用你的配置
  2. 提供合理的默认值,但允许用户自定义
  3. 使用spring-boot-configuration-processor生成元数据,提供IDE支持
  4. 遵循命名约定:XxxAutoConfiguration作为配置类名,XxxProperties作为属性类名

3. 配置管理

Spring Boot提供了灵活且强大的配置机制,支持多种配置方式和配置优先级。

核心概念

🔧 配置管理:Spring Boot允许通过属性文件、YAML文件、环境变量、命令行参数等多种方式配置应用,并提供了灵活的属性绑定功能。

3.1 配置文件格式

Spring Boot支持Properties和YAML两种主要的配置文件格式。

Properties是传统的Java配置文件格式,使用键值对方式:

application.properties
properties
1# 服务器配置
2server.port=8080
3server.servlet.context-path=/api
4
5# 数据源配置
6spring.datasource.url=jdbc:mysql://localhost:3306/mydb
7spring.datasource.username=user
8spring.datasource.password=password
9spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
10
11# JPA配置
12spring.jpa.hibernate.ddl-auto=update
13spring.jpa.show-sql=true
14spring.jpa.properties.hibernate.format_sql=true
15
16# 自定义属性
17app.name=My Spring Boot App
18app.description=A sample Spring Boot application
19app.version=1.0.0

Properties格式特点

优点

  • 传统格式,兼容性好
  • 工具支持广泛
  • 语法简单直观

缺点

  • 层次结构不直观
  • 不支持复杂数据类型
  • 配置项多时不易维护

3.2 多环境配置

Spring Boot通过profiles机制支持多环境配置,可以根据不同的环境(如开发、测试、生产)加载不同的配置。

使用不同文件配置不同环境:

application.yml(通用配置)
yaml
1spring:
2 application:
3 name: my-application
4
5logging:
6level:
7 root: INFO
application-dev.yml(开发环境)
yaml
1spring:
2 datasource:
3 url: jdbc:h2:mem:devdb
4 username: sa
5 password:
6
7logging:
8 level:
9 com.example: DEBUG
application-prod.yml(生产环境)
yaml
1spring:
2 datasource:
3 url: jdbc:mysql://prod-server:3306/proddb
4 username: produser
5 password: prodpass
6
7logging:
8 level:
9 root: WARN
10 com.example: INFO

3.3 配置属性绑定

Spring Boot提供了强大的属性绑定机制,可以将配置文件中的属性绑定到Java对象。

@Value注解是属性注入的基本方式,用于单个属性的注入:

@Value注解示例
java
1@RestController
2public class AppController {
3
4 @Value("${app.name}")
5 private String appName;
6
7 @Value("${app.description:Default description}") // 提供默认值
8 private String appDescription;
9
10 @Value("${server.port}")
11 private int serverPort;
12
13 @Value("${app.enabled:false}") // 默认为false
14 private boolean appEnabled;
15
16 @Value("${app.list-values}")
17 private String[] listValues;
18
19 @Value("#{${app.map-values}}") // 注入Map需要SpEL表达式
20 private Map<String, Integer> mapValues;
21
22 @GetMapping("/config")
23 public Map<String, Object> getConfig() {
24 Map<String, Object> config = new HashMap<>();
25 config.put("name", appName);
26 config.put("description", appDescription);
27 config.put("port", serverPort);
28 config.put("enabled", appEnabled);
29 config.put("listValues", listValues);
30 config.put("mapValues", mapValues);
31 return config;
32 }
33}

@ConfigurationProperties vs @Value

特性@ConfigurationProperties@Value
松散绑定支持(如my-service-url绑定到myServiceUrl)不支持
元数据支持支持(可生成配置元数据)不支持
复杂类型支持嵌套对象、列表、Map等有限支持
默认值在类中定义在注解中定义
批量导入一个类绑定多个属性每个属性单独绑定
表达式语言不支持支持SpEL
属性转换自动类型转换有限的类型转换
校验支持JSR-303注解不支持
配置优先级

Spring Boot配置的优先级从高到低:

  1. 命令行参数
  2. Java系统属性(System.getProperties())
  3. 操作系统环境变量
  4. application-{profile}.properties外部文件
  5. application.properties外部文件
  6. application-{profile}.properties内部文件
  7. application.properties内部文件
  8. @PropertySource注解引入的属性文件
  9. 默认属性

3.4 属性加密与敏感信息

在实际应用中,配置文件可能包含敏感信息(如数据库密码、API密钥等),Spring Boot提供了多种方式处理敏感配置:

使用Jasypt加密配置示例
java
1// 添加Jasypt依赖
2// implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4'
3
4@SpringBootApplication
5@EnableEncryptableProperties
6public class MyApplication {
7
8 public static void main(String[] args) {
9 SpringApplication.run(MyApplication.class, args);
10 }
11}
加密属性示例
yaml
1spring:
2 datasource:
3 url: jdbc:mysql://localhost:3306/mydb
4 username: dbuser
5 # 加密的密码
6 password: ENC(G5n+K5LQum+dFiNbgd+F5kAm0FyYpaIP)
加密命令
shell
1# 加密密码
2java -jar jasypt-1.9.3.jar encrypt.bat input=mypassword password=mysecretkey

4. Spring Boot启动流程

Spring Boot启动过程是一个复杂而精巧的流程,其中包含了多个关键步骤和事件。

核心概念

🚀 启动流程:Spring Boot应用启动时会经历创建SpringApplication对象、准备环境、创建上下文、加载Bean定义和刷新上下文等一系列步骤,每个步骤都有特定的作用和事件通知机制。

4.1 启动流程详解

Spring Boot的启动流程可以分为以下几个关键步骤:

Spring Boot启动流程步骤

  1. 创建SpringApplication对象

    • 推断应用类型(SERVLET、REACTIVE、NONE)
    • 设置初始化器(ApplicationContextInitializer)
    • 设置监听器(ApplicationListener)
    • 推断主应用类
  2. 运行SpringApplication

    • 创建并启动StopWatch(用于记录启动时间)
    • 创建应用上下文环境(ConfigurableEnvironment)
    • 准备上下文(ApplicationContext)
    • 刷新上下文
    • 应用上下文后置处理
    • 发布应用启动完成事件
  3. 准备Environment

    • 创建和配置环境对象
    • 读取所有配置源的配置属性
    • 处理profiles
  4. 创建ApplicationContext

    • 根据应用类型创建对应的上下文
      • SERVLET类型:AnnotationConfigServletWebServerApplicationContext
      • REACTIVE类型:AnnotationConfigReactiveWebServerApplicationContext
      • 非Web应用:AnnotationConfigApplicationContext
  5. 刷新ApplicationContext

    • 处理Bean定义
    • 初始化非延迟加载的单例Bean
    • 启动嵌入式Web服务器(如果是Web应用)
  6. 执行Runner

    • 按顺序执行所有CommandLineRunnerApplicationRunner
SpringApplication启动源码分析
SpringApplication核心方法
java
1public ConfigurableApplicationContext run(String... args) {
2 StopWatch stopWatch = new StopWatch();
3 stopWatch.start();
4 ConfigurableApplicationContext context = null;
5 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
6
7 // 1. 配置headless属性
8 configureHeadlessProperty();
9
10 // 2. 获取并启动所有的SpringApplicationRunListener
11 SpringApplicationRunListeners listeners = getRunListeners(args);
12 listeners.starting();
13
14 try {
15 // 3. 创建ApplicationArguments对象
16 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
17
18 // 4. 准备环境
19 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
20 configureIgnoreBeanInfo(environment);
21
22 // 5. 打印Banner
23 Banner printedBanner = printBanner(environment);
24
25 // 6. 创建ApplicationContext
26 context = createApplicationContext();
27
28 // 7. 获取异常报告器
29 exceptionReporters = getSpringFactoriesInstances(
30 SpringBootExceptionReporter.class,
31 new Class[] { ConfigurableApplicationContext.class }, context);
32
33 // 8. 准备上下文
34 prepareContext(context, environment, listeners, applicationArguments, printedBanner);
35
36 // 9. 刷新上下文
37 refreshContext(context);
38
39 // 10. 刷新上下文后的操作
40 afterRefresh(context, applicationArguments);
41
42 // 11. 停止计时器并输出启动日志
43 stopWatch.stop();
44 if (this.logStartupInfo) {
45 new StartupInfoLogger(this.mainApplicationClass)
46 .logStarted(getApplicationLog(), stopWatch);
47 }
48
49 // 12. 发布应用已启动事件
50 listeners.started(context);
51
52 // 13. 调用所有Runner
53 callRunners(context, applicationArguments);
54 }
55 catch (Throwable ex) {
56 handleRunFailure(context, ex, exceptionReporters, listeners);
57 throw new IllegalStateException(ex);
58 }
59
60 try {
61 // 14. 发布应用就绪事件
62 listeners.running(context);
63 }
64 catch (Throwable ex) {
65 handleRunFailure(context, ex, exceptionReporters, null);
66 throw new IllegalStateException(ex);
67 }
68
69 // 15. 返回上下文
70 return context;
71}

4.2 事件监听机制

Spring Boot启动过程中会发布一系列事件,应用可以通过监听这些事件来执行特定的操作。

Spring Boot支持两种方式注册事件监听器:

ApplicationListener实现
java
1@Component
2public class MyApplicationStartingListener
3 implements ApplicationListener<ApplicationStartingEvent> {
4
5 private static final Logger logger = LoggerFactory.getLogger(MyApplicationStartingListener.class);
6
7 @Override
8 public void onApplicationEvent(ApplicationStartingEvent event) {
9 logger.info("应用正在启动...");
10 // 在应用启动开始时执行一些操作
11 }
12}
@EventListener注解
java
1@Component
2public class MyEventListener {
3
4 private static final Logger logger = LoggerFactory.getLogger(MyEventListener.class);
5
6 @EventListener
7 public void handleApplicationReady(ApplicationReadyEvent event) {
8 logger.info("应用已准备就绪!");
9 // 应用准备就绪时执行一些操作
10 }
11
12 @EventListener
13 public void handleContextRefreshed(ContextRefreshedEvent event) {
14 logger.info("上下文已刷新!");
15 // 上下文刷新时执行一些操作
16 }
17}
注意事项

对于在Spring上下文创建之前触发的事件(如ApplicationStartingEvent),监听器不能通过@Component注册,必须通过META-INF/spring.factories文件或在SpringApplication.addListeners()方法中显式添加。

META-INF/spring.factories
properties
1# 注册早期事件监听器
2org.springframework.context.ApplicationListener=\
3com.example.MyApplicationStartingListener,\
4com.example.MyEnvironmentPreparedListener

4.3 嵌入式容器启动

对于Web应用,Spring Boot会在启动过程中自动配置和启动嵌入式Web服务器。

内嵌容器启动过程
java
1// ServletWebServerApplicationContext类中的createWebServer方法
2private void createWebServer() {
3 WebServer webServer = this.webServer;
4 ServletContext servletContext = getServletContext();
5
6 if (webServer == null && servletContext == null) {
7 // 获取ServletWebServerFactory
8 ServletWebServerFactory factory = getWebServerFactory();
9
10 // 创建WebServer
11 this.webServer = factory.getWebServer(getSelfInitializer());
12
13 // 注册特殊的Bean
14 getBeanFactory().registerSingleton("webServerGracefulShutdown",
15 new WebServerGracefulShutdownLifecycle(this.webServer));
16 getBeanFactory().registerSingleton("webServerStartStop",
17 new WebServerStartStopLifecycle(this, this.webServer));
18 }
19 else if (servletContext != null) {
20 try {
21 getSelfInitializer().onStartup(servletContext);
22 }
23 catch (ServletException ex) {
24 throw new ApplicationContextException("Cannot initialize servlet context", ex);
25 }
26 }
27
28 // 初始化属性源
29 initPropertySources();
30}

4.4 自动配置的处理

在Spring Boot启动过程中,自动配置是一个重要的环节,它发生在ApplicationContext刷新阶段。

自动配置的核心过程:

  1. 在应用上下文刷新阶段,处理配置类上的@Import注解
  2. 检测到@EnableAutoConfiguration注解,调用AutoConfigurationImportSelector
  3. AutoConfigurationImportSelectorMETA-INF/spring.factories中加载自动配置类
  4. 对这些自动配置类应用条件过滤(@ConditionalOnXXX
  5. 将筛选后的自动配置类注册为Bean定义
  6. 在Bean初始化阶段创建和配置这些Bean

5. 起步依赖

Spring Boot的起步依赖是一组精心设计的依赖描述符,用于简化依赖管理。

核心概念

📦 起步依赖:Spring Boot的起步依赖是一种特殊的Maven依赖,它可以传递引入所有需要的依赖项,简化项目的依赖管理,保证依赖版本的兼容性。

5.1 起步依赖原理

Spring Boot起步依赖的核心原理是通过Maven的依赖传递机制,将一组相关的依赖聚合在一起,形成针对特定功能的依赖集合。

起步依赖的工作原理

  1. 依赖聚合:将一组相关的依赖项聚合在一个POM文件中
  2. 依赖传递:通过Maven的依赖传递机制,将所有必要的依赖项引入项目
  3. 版本管理:通过spring-boot-dependencies统一管理所有依赖项的版本
  4. 自动配置:与自动配置机制结合,根据依赖自动配置应用
Spring Boot依赖管理示例
xml
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-parent</artifactId>
4 <version>2.7.0</version>
5 <type>pom</type>
6 <scope>import</scope>
7</dependency>
spring-boot-starter-web依赖结构
xml
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-web</artifactId>
4</dependency>
5
6<!-- 这个依赖会传递性地引入以下依赖 -->
7<!-- spring-boot-starter(核心启动器) -->
8<!-- spring-boot-starter-json(JSON支持) -->
9<!-- spring-boot-starter-tomcat(Tomcat服务器) -->
10<!-- spring-web(Spring Web核心) -->
11<!-- spring-webmvc(Spring MVC) -->
12<!-- ... 以及其他传递性依赖 -->

5.2 常用起步依赖

Spring Boot提供了许多常用的起步依赖,涵盖了不同的应用场景和功能。

Web应用起步依赖
xml
1<!-- Spring MVC Web应用 -->
2<dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-starter-web</artifactId>
5</dependency>
6
7<!-- 响应式Web应用 -->
8<dependency>
9 <groupId>org.springframework.boot</groupId>
10 <artifactId>spring-boot-starter-webflux</artifactId>
11</dependency>
12
13<!-- WebSocket支持 -->
14<dependency>
15 <groupId>org.springframework.boot</groupId>
16 <artifactId>spring-boot-starter-websocket</artifactId>
17</dependency>
18
19<!-- 安全支持 -->
20<dependency>
21 <groupId>org.springframework.boot</groupId>
22 <artifactId>spring-boot-starter-security</artifactId>
23</dependency>

Web起步依赖特点

spring-boot-starter-web包含:

  • Spring MVC
  • 内嵌Tomcat服务器
  • Jackson JSON处理
  • 验证框架
  • 日志和监控

spring-boot-starter-webflux包含:

  • Spring WebFlux(响应式Web框架)
  • Netty或Undertow服务器
  • Reactive Streams支持

spring-boot-starter-security包含:

  • Spring Security
  • 认证和授权支持
  • 安全过滤器链

5.3 自定义起步依赖

在实际项目中,你可能需要创建自己的起步依赖,以统一项目或团队的依赖管理。

自动配置模块POM
xml
1<project>
2 <modelVersion>4.0.0</modelVersion>
3 <groupId>com.example</groupId>
4 <artifactId>example-spring-boot-autoconfigure</artifactId>
5 <version>1.0.0</version>
6 <name>Example Spring Boot Autoconfigure</name>
7
8 <dependencies>
9 <dependency>
10 <groupId>org.springframework.boot</groupId>
11 <artifactId>spring-boot-autoconfigure</artifactId>
12 </dependency>
13
14 <!-- 可选依赖,用于配置属性处理 -->
15 <dependency>
16 <groupId>org.springframework.boot</groupId>
17 <artifactId>spring-boot-configuration-processor</artifactId>
18 <optional>true</optional>
19 </dependency>
20
21 <!-- 核心功能依赖 -->
22 <dependency>
23 <groupId>com.example</groupId>
24 <artifactId>example-library</artifactId>
25 <version>1.0.0</version>
26 </dependency>
27</dependencies>
28</project>
配置属性类
java
1@ConfigurationProperties(prefix = "example")
2public class ExampleProperties {
3
4 /**
5 * 是否启用该功能
6 */
7 private boolean enabled = true;
8
9 /**
10 * API基础URL
11 */
12 private String baseUrl = "https://api.example.com";
13
14 /**
15 * 连接超时时间(毫秒)
16 */
17 private int timeout = 3000;
18
19 // getter和setter方法
20}
自动配置类
java
1@Configuration
2@ConditionalOnClass(ExampleService.class)
3@EnableConfigurationProperties(ExampleProperties.class)
4public class ExampleAutoConfiguration {
5
6 private final ExampleProperties properties;
7
8 public ExampleAutoConfiguration(ExampleProperties properties) {
9 this.properties = properties;
10 }
11
12 @Bean
13 @ConditionalOnMissingBean
14 @ConditionalOnProperty(prefix = "example", name = "enabled", havingValue = "true", matchIfMissing = true)
15 public ExampleService exampleService() {
16 ExampleService service = new ExampleService();
17 service.setBaseUrl(properties.getBaseUrl());
18 service.setTimeout(properties.getTimeout());
19 return service;
20 }
21
22 @Bean
23 @ConditionalOnMissingBean
24 @ConditionalOnBean(ExampleService.class)
25 public ExampleClient exampleClient(ExampleService service) {
26 return new ExampleClient(service);
27 }
28}
自定义起步依赖最佳实践

创建自定义起步依赖时,应遵循以下最佳实践:

  1. 分离自动配置模块和起步依赖模块,使得用户可以选择性使用自动配置
  2. 使用条件注解避免强制配置,允许用户覆盖默认配置
  3. 提供配置属性类,允许用户通过配置文件自定义行为
  4. 生成元数据,提供良好的IDE支持
  5. 遵循命名约定:xxx-spring-boot-autoconfigurexxx-spring-boot-starter
  6. 不要将spring-boot-starter-*作为依赖的名称(避免与官方起步依赖混淆)

6. 监控与管理

Spring Boot Actuator是Spring Boot的一个子项目,提供了生产就绪特性,帮助你监控和管理应用。

核心概念

📊 Actuator:Spring Boot Actuator提供了监控和管理Spring Boot应用程序的生产就绪功能,包括健康检查、指标收集、环境信息和HTTP跟踪等。

6.1 Actuator基础配置

Spring Boot Actuator提供了一系列的HTTP端点,可以用来监控和管理应用程序。

Actuator依赖
xml
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-actuator</artifactId>
4</dependency>
基础配置
yaml
1management:
2endpoints:
3 web:
4 exposure:
5 # 暴露所有端点
6 include: "*"
7 # 排除敏感端点
8 exclude: "env,beans"
9endpoint:
10 health:
11 show-details: always
12 shutdown:
13 enabled: true
14 info:
15 env:
16 enabled: true

Actuator端点访问

默认情况下,所有端点都通过HTTP暴露在/actuator路径下:

  • /actuator/health - 应用健康状态
  • /actuator/info - 应用信息
  • /actuator/metrics - 应用指标
  • /actuator/env - 环境变量
  • /actuator/mappings - 请求映射
  • /actuator/beans - 应用中的所有Bean
  • /actuator/configprops - 配置属性
  • /actuator/loggers - 日志级别管理

6.2 健康检查

健康检查是Actuator的核心功能,用于监控应用及其依赖的状态。

自定义健康检查
java
1@Component
2public class CustomHealthIndicator implements HealthIndicator {
3
4 @Override
5 public Health health() {
6 boolean isHealthy = checkHealth(); // 自定义健康检查逻辑
7
8 if (isHealthy) {
9 return Health.up()
10 .withDetail("message", "服务运行正常")
11 .withDetail("timestamp", System.currentTimeMillis())
12 .build();
13 } else {
14 return Health.down()
15 .withDetail("message", "服务异常")
16 .withDetail("timestamp", System.currentTimeMillis())
17 .withDetail("error", "具体错误信息")
18 .build();
19 }
20 }
21
22 private boolean checkHealth() {
23 // 实现健康检查逻辑
24 try {
25 // 检查关键服务是否可用
26 // 例如:数据库连接、缓存连接、外部服务调用等
27 return true;
28 } catch (Exception e) {
29 return false;
30 }
31 }
32}

6.3 度量指标

Spring Boot 2.x引入了Micrometer作为应用指标门面,支持多种监控系统,如Prometheus、InfluxDB、New Relic等。

添加Prometheus支持
xml
1<dependency>
2 <groupId>io.micrometer</groupId>
3 <artifactId>micrometer-registry-prometheus</artifactId>
4</dependency>
Prometheus配置
yaml
1management:
2 endpoints:
3 web:
4 exposure:
5 include: prometheus
6 metrics:
7 export:
8 prometheus:
9 enabled: true
prometheus.yml配置
yaml
1scrape_configs:
2 - job_name: 'spring-boot-app'
3 scrape_interval: 5s
4 metrics_path: '/actuator/prometheus'
5 static_configs:
6 - targets: ['localhost:8080']

6.4 自定义端点

你可以创建自己的Actuator端点来暴露特定于应用的信息或操作。

自定义Actuator端点
java
1@Component
2@Endpoint(id = "application-status")
3public class ApplicationStatusEndpoint {
4
5 private final StatusService statusService;
6
7 public ApplicationStatusEndpoint(StatusService statusService) {
8 this.statusService = statusService;
9 }
10
11 @ReadOperation
12 public Map<String, Object> status() {
13 Map<String, Object> status = new HashMap<>();
14 status.put("status", statusService.getStatus());
15 status.put("uptime", statusService.getUptime());
16 status.put("startTime", statusService.getStartTime());
17 status.put("activeSessions", statusService.getActiveSessions());
18 status.put("systemLoad", statusService.getSystemLoad());
19 return status;
20 }
21
22 @WriteOperation
23 public Map<String, String> updateStatus(@Selector String action) {
24 Map<String, String> result = new HashMap<>();
25 switch (action) {
26 case "pause":
27 statusService.pauseProcessing();
28 result.put("result", "Processing paused");
29 break;
30 case "resume":
31 statusService.resumeProcessing();
32 result.put("result", "Processing resumed");
33 break;
34 default:
35 result.put("error", "Unknown action: " + action);
36 }
37 return result;
38 }
39}

7. 部署与打包

Spring Boot提供了多种灵活的部署选项,从传统的WAR部署到现代的容器化部署。

核心概念

📦 Spring Boot打包:Spring Boot应用可以打包成可执行的JAR或WAR文件,包含所有依赖和嵌入式服务器,实现"一次构建,到处运行"。

7.1 打包选项

Maven打包配置
xml
1<build>
2 <plugins>
3 <plugin>
4 <groupId>org.springframework.boot</groupId>
5 <artifactId>spring-boot-maven-plugin</artifactId>
6 <configuration>
7 <executable>true</executable>
8 <excludes>
9 <exclude>
10 <groupId>org.projectlombok</groupId>
11 <artifactId>lombok</artifactId>
12 </exclude>
13 </excludes>
14 </configuration>
15 </plugin>
16 </plugins>
17</build>
打包命令
shell
1# Maven打包
2mvn clean package
3
4# 运行JAR
5java -jar target/myapp-0.0.1-SNAPSHOT.jar

可执行JAR特点

  • 包含应用的所有代码和依赖
  • 内置嵌入式Web服务器
  • 无需额外安装Tomcat等容器
  • 可以直接通过java -jar命令运行
  • 支持命令行参数配置

7.2 部署方式

Spring Boot应用支持多种部署方式,从传统到云原生:

部署方式比较

部署方式优点缺点适用场景
独立JAR部署简单、自包含资源隔离弱简单应用、开发环境
传统服务器部署利用服务器高级特性配置复杂传统企业环境
Docker容器化环境一致性、隔离性好需要容器运行环境微服务、DevOps环境
Kubernetes编排高可用、自动伸缩复杂度高大规模微服务集群
云平台PaaS低运维成本供应商锁定初创企业、中小规模应用

7.3 生产环境最佳实践

在将Spring Boot应用部署到生产环境时,应遵循以下最佳实践:

环境特定配置
yaml
1# 通过环境变量注入关键配置
2spring:
3 datasource:
4 url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:myapp}
5 username: ${DB_USER:root}
6 password: ${DB_PASSWORD:secret}
生产环境启动
shell
1# 使用外部配置文件
2java -jar app.jar --spring.config.location=file:///path/to/production.yml
3
4# 指定活动profile
5java -jar app.jar --spring.profiles.active=prod
6
7# 覆盖特定配置
8java -jar app.jar --server.port=9000 --logging.level.root=WARN
配置管理最佳实践
  • 使用环境变量注入敏感信息
  • 避免在代码中硬编码配置
  • 使用配置服务器集中管理配置
  • 使用多环境profile分离配置
  • 使用密文存储敏感信息

8. 总结

Spring Boot通过简化配置、提供默认实现,极大地提高了Spring应用的开发效率,成为现代Java应用开发的标准工具。

Spring Boot学习路径

🚀 Spring Boot学习建议

  1. 掌握Spring基础知识(IoC、AOP)
  2. 理解自动配置和起步依赖的原理
  3. 学习配置管理和属性绑定
  4. 了解启动流程和生命周期事件
  5. 熟悉Actuator监控和管理
  6. 掌握不同的部署选项
  7. 实践微服务和云原生开发

Spring Boot让开发者能够专注于业务逻辑的开发,而不必过多关注底层框架的配置细节。它与Spring Cloud生态系统的完美结合,更是为微服务架构和云原生应用开发提供了强大的支持。

9. 面试题精选

Q1: 什么是Spring Boot?它有什么优势?

答: Spring Boot是Spring框架的扩展,专注于简化Spring应用的初始搭建和开发过程。主要优势包括:

  • 自动配置:减少配置,自动配置大部分组件
  • 起步依赖:简化依赖管理,解决版本兼容性问题
  • 内嵌服务器:内置Tomcat等服务器,无需部署WAR文件
  • Actuator:提供监控和管理功能
  • 无代码生成和XML配置:减少样板代码
  • 独立运行:可以像普通Java程序一样运行

Q2: Spring Boot的自动配置原理是什么?

答: Spring Boot自动配置基于以下机制:

  1. 通过@EnableAutoConfiguration注解启用自动配置
  2. 该注解通过@Import导入AutoConfigurationImportSelector
  3. AutoConfigurationImportSelector会从所有JAR包中的META-INF/spring.factories文件加载EnableAutoConfiguration配置项
  4. 根据条件注解(@ConditionalOnClass, @ConditionalOnBean等)判断哪些配置类生效
  5. 匹配条件的配置类会被注册为Bean,创建需要的组件

Q3: Spring Boot常用的核心注解有哪些?

答: Spring Boot常用的核心注解:

  • @SpringBootApplication:包含三个注解(@Configuration, @EnableAutoConfiguration, @ComponentScan
  • @EnableAutoConfiguration:启用自动配置
  • @Configuration:标记配置类
  • @ComponentScan:组件扫描
  • @ConfigurationProperties:绑定配置属性
  • @ConditionalOnXXX:条件化配置(如@ConditionalOnClass, @ConditionalOnBean, @ConditionalOnProperty等)
  • @SpringBootConfiguration:特定于Spring Boot的配置类
  • @EnableConfigurationProperties:启用@ConfigurationProperties注解

Q4: Spring Boot如何管理配置文件?配置文件的优先级如何?

答: Spring Boot支持多种配置方式,主要有:

  • application.propertiesapplication.yml文件
  • 特定环境的配置文件(如application-dev.yml
  • 环境变量
  • 命令行参数

配置优先级从高到低:

  1. 命令行参数
  2. Java系统属性(System.getProperties()
  3. 操作系统环境变量
  4. application-{profile}.properties(外部配置)
  5. application.properties(外部配置)
  6. application-{profile}.properties(内部配置)
  7. application.properties(内部配置)
  8. @PropertySource注解引入的属性
  9. 默认属性

Q5: 如何理解Spring Boot的起步依赖(Starter)?

答: Spring Boot起步依赖是一种特殊的Maven或Gradle依赖,用于简化项目依赖管理:

  • 一个起步依赖通常会引入一组功能相关的传递性依赖
  • 通过spring-boot-starter-*命名,如spring-boot-starter-web
  • 提供了版本管理,确保依赖组件间的兼容性
  • 与自动配置协同工作,自动配置需要的组件
  • 减少了手动添加依赖的工作量和版本冲突的风险

Q6: Spring Boot的启动流程是怎样的?

答: Spring Boot启动流程主要包括:

  1. 创建SpringApplication对象
    • 确定应用类型(SERVLET、REACTIVE、NONE)
    • 设置初始化器和监听器
    • 推断主应用类
  2. 运行SpringApplication
    • 创建并启动计时器
    • 发布ApplicationStartingEvent事件
    • 准备环境并加载配置
    • 创建ApplicationContext
    • 准备上下文,加载Bean定义
    • 刷新上下文,实例化单例Bean
    • 发布ApplicationStartedEvent事件
    • 调用ApplicationRunnerCommandLineRunner
    • 发布ApplicationReadyEvent事件

Q7: 如何在Spring Boot中集成自定义配置?

答: 在Spring Boot中集成自定义配置有多种方式:

  1. 使用@Value注解直接注入单个属性
    java
    1@Value("${custom.property}")
    2private String customProperty;
  2. 使用@ConfigurationProperties绑定配置到Java类
    java
    1@Component
    2@ConfigurationProperties(prefix = "custom")
    3public class CustomProperties {
    4 private String property;
    5 // getters and setters
    6}
  3. 创建自定义的配置类:
    java
    1@Configuration
    2public class CustomConfiguration {
    3 @Bean
    4 public SomeBean someBean() {
    5 return new SomeBean();
    6 }
    7}

Q8: Spring Boot中如何实现安全认证?

答: Spring Boot中实现安全认证主要通过Spring Security:

  1. 添加依赖:spring-boot-starter-security
  2. 创建配置类:
    java
    1@Configuration
    2@EnableWebSecurity
    3public class SecurityConfig extends WebSecurityConfigurerAdapter {
    4
    5 @Override
    6 protected void configure(HttpSecurity http) throws Exception {
    7 http
    8 .authorizeRequests()
    9 .antMatchers("/public/**").permitAll()
    10 .anyRequest().authenticated()
    11 .and()
    12 .formLogin()
    13 .loginPage("/login")
    14 .permitAll()
    15 .and()
    16 .logout()
    17 .permitAll();
    18 }
    19
    20 @Override
    21 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    22 auth.inMemoryAuthentication()
    23 .withUser("user").password("{noop}password").roles("USER");
    24 }
    25}
  3. 对于生产环境,可以配置JDBC认证、OAuth2、LDAP等认证方式

Q9: Spring Boot Actuator的作用是什么?有哪些常用端点?

答: Spring Boot Actuator提供生产就绪功能,用于监控和管理应用:

作用:

  • 监控应用健康状态
  • 收集应用指标
  • 查看应用配置
  • 查看环境信息
  • 管理日志级别
  • 查看线程信息

常用端点:

  • /actuator/health:健康状态
  • /actuator/info:应用信息
  • /actuator/metrics:指标收集
  • /actuator/env:环境变量
  • /actuator/configprops:配置属性
  • /actuator/mappings:请求映射
  • /actuator/beans:应用中的Bean
  • /actuator/loggers:日志配置

Q10: 如何自定义Spring Boot的Banner?

答: 自定义Spring Boot启动Banner的方法:

  1. src/main/resources目录下创建banner.txt文件
  2. 使用文本/ASCII艺术设计Banner
  3. 也可以通过代码方式设置:
    java
    1SpringApplication app = new SpringApplication(MyApp.class);
    2app.setBannerMode(Banner.Mode.OFF); // 关闭Banner
    3// 或者设置自定义Banner
    4app.setBanner(new ResourceBanner(new ClassPathResource("path/to/banner.txt")));
    5app.run(args);
  4. 可以在配置文件中设置:
    properties
    1spring.main.banner-mode=off
    2# 或者指定文件
    3spring.banner.location=classpath:path/to/banner.txt

参与讨论