38 Spring Boot入门——自动配置、核心注解与Starter机制

目录

  • [🍃 38 Spring Boot入门------自动配置、核心注解与Starter机制](#🍃 38 Spring Boot入门——自动配置、核心注解与Starter机制)
    • [一、Spring Boot概述](#一、Spring Boot概述)
      • [1.1 为什么需要Spring Boot](#1.1 为什么需要Spring Boot)
      • [1.2 Spring Boot核心特性](#1.2 Spring Boot核心特性)
      • [1.3 Spring Boot与Spring的关系](#1.3 Spring Boot与Spring的关系)
    • [二、快速创建Spring Boot项目](#二、快速创建Spring Boot项目)
      • [2.1 使用Spring Initializr](#2.1 使用Spring Initializr)
      • [2.2 Maven项目结构](#2.2 Maven项目结构)
      • [2.3 pom.xml核心配置](#2.3 pom.xml核心配置)
      • [2.4 启动类](#2.4 启动类)
      • [2.5 第一个REST接口](#2.5 第一个REST接口)
    • 三、核心注解详解
      • [3.1 `@SpringBootApplication`](#3.1 @SpringBootApplication)
      • [3.2 Web层注解](#3.2 Web层注解)
      • [3.3 依赖注入注解](#3.3 依赖注入注解)
      • [3.4 配置相关注解](#3.4 配置相关注解)
    • 四、自动配置原理
      • [4.1 自动配置流程](#4.1 自动配置流程)
      • [4.2 `@Conditional`条件注解族](#4.2 @Conditional条件注解族)
      • [4.3 源码解析:以DataSource自动配置为例](#4.3 源码解析:以DataSource自动配置为例)
      • [4.4 手动覆盖自动配置](#4.4 手动覆盖自动配置)
      • [4.5 查看自动配置报告](#4.5 查看自动配置报告)
    • 五、配置文件详解
      • [5.1 两种配置文件格式](#5.1 两种配置文件格式)
      • [5.2 配置文件加载优先级](#5.2 配置文件加载优先级)
      • [5.3 自定义配置属性绑定](#5.3 自定义配置属性绑定)
      • [5.4 类型安全的属性校验](#5.4 类型安全的属性校验)
      • [5.5 复杂类型配置](#5.5 复杂类型配置)
    • 六、多环境配置
      • [6.1 多Profile文件](#6.1 多Profile文件)
      • [6.2 激活Profile的多种方式](#6.2 激活Profile的多种方式)
      • [6.3 Profile分组(Spring Boot 2.4+)](#6.3 Profile分组(Spring Boot 2.4+))
      • [6.4 Profile条件装配](#6.4 Profile条件装配)
    • 七、Starter机制
      • [7.1 什么是Starter](#7.1 什么是Starter)
      • [7.2 常用Starter一览](#7.2 常用Starter一览)
      • [7.3 Starter的工作原理](#7.3 Starter的工作原理)
      • [7.4 自定义Starter](#7.4 自定义Starter)
      • [7.5 自定义Starter的最佳实践](#7.5 自定义Starter的最佳实践)
    • [八、Spring Boot生命周期与扩展点](#八、Spring Boot生命周期与扩展点)
      • [8.1 启动流程](#8.1 启动流程)
      • [8.2 常用扩展点](#8.2 常用扩展点)
      • [8.3 优雅关闭](#8.3 优雅关闭)
    • 九、常见面试题解析
    • 十、总结与下篇预告

🍃 38 Spring Boot入门------自动配置、核心注解与Starter机制

更新日期 :2026年6月 | Java入门到精通系列 · 第五阶段·企业级开发

© 版权声明:本文为原创技术文章,转载请联系作者并注明出处。



一、Spring Boot概述

1.1 为什么需要Spring Boot

在Spring Boot出现之前,搭建一个Spring Web应用需要大量的XML配置、依赖管理和环境搭建工作。一个简单的"Hello World"项目就需要:

  • 配置web.xml
  • 配置applicationContext.xml
  • 配置Spring MVC的DispatcherServlet
  • 管理几十个Maven依赖的版本兼容性
  • 部署到外部Tomcat

Spring Boot 的核心理念是:约定优于配置(Convention over Configuration),让开发者用最少的配置快速启动一个Spring应用。

1.2 Spring Boot核心特性

特性 说明 解决的问题
自动配置 根据类路径自动推断并配置Bean 消除大量XML配置
Starter依赖 一站式依赖管理 解决版本冲突
内嵌服务器 内置Tomcat/Jetty/Undertow 无需外部部署
Actuator 生产级监控端点 应用健康检查
配置文件 统一的application.yml 配置管理标准化
CLI工具 命令行快速开发 原型验证

1.3 Spring Boot与Spring的关系

复制代码
┌──────────────────────────────────────────┐
│            Spring Boot                    │
│  ┌─────────────────────────────────────┐ │
│  │        自动配置 (Auto-configuration)  │ │
│  ├─────────────────────────────────────┤ │
│  │        Starter依赖                   │ │
│  ├─────────────────────────────────────┤ │
│  │   ┌──────────────────────────────┐  │ │
│  │   │        Spring Framework       │  │ │
│  │   │  ┌────────┐  ┌────────────┐  │  │ │
│  │   │  │  IoC    │  │   AOP      │  │  │ │
│  │   │  └────────┘  └────────────┘  │  │ │
│  │   │  ┌────────┐  ┌────────────┐  │  │ │
│  │   │  │  MVC   │  │  Security  │  │  │ │
│  │   │  └────────┘  └────────────┘  │  │ │
│  │   └──────────────────────────────┘  │ │
│  └─────────────────────────────────────┘ │
└──────────────────────────────────────────┘

Spring Boot 不是 Spring的替代品,而是Spring的脚手架,它建立在Spring Framework之上,简化了Spring应用的初始搭建和开发过程。


二、快速创建Spring Boot项目

2.1 使用Spring Initializr

最简单的方式是访问 start.spring.io 或在IDEA中创建:

推荐配置:

选项 推荐值
Project Maven
Language Java
Spring Boot 3.x(最新稳定版)
Group com.example
Artifact demo
Packaging Jar
Java 17+

2.2 Maven项目结构

复制代码
demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       └── DemoApplication.java    # 启动类
│   │   ├── resources/
│   │   │   ├── application.yml              # 主配置文件
│   │   │   ├── application-dev.yml          # 开发环境配置
│   │   │   ├── application-prod.yml         # 生产环境配置
│   │   │   ├── static/                      # 静态资源
│   │   │   └── templates/                   # 模板文件
│   │   └── webapp/                          # (可选)传统Web资源
│   └── test/
│       └── java/
│           └── com/example/demo/
│               └── DemoApplicationTests.java
├── pom.xml
└── mvnw / mvnw.cmd                         # Maven Wrapper

2.3 pom.xml核心配置

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 父级依赖:统一管理版本号 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Spring Boot Demo Project</description>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <!-- Web启动器:包含Spring MVC + 内嵌Tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 测试启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.4 启动类

java 复制代码
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication  // 核心注解,开启自动配置
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

运行main方法,一个Web应用就启动了,默认监听8080端口!

2.5 第一个REST接口

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Boot!";
    }
}

访问 http://localhost:8080/hello 即可看到返回结果。


三、核心注解详解

3.1 @SpringBootApplication

这是Spring Boot最核心的注解,它是一个组合注解

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration      // 标记为配置类
@EnableAutoConfiguration      // 开启自动配置
@ComponentScan                // 组件扫描
public @interface SpringBootApplication {
    // ...
}

等价于以下三个注解的组合:

注解 作用
@SpringBootConfiguration 标记当前类为配置类(本质是@Configuration
@EnableAutoConfiguration 开启Spring Boot自动配置机制
@ComponentScan 自动扫描当前包及子包下的组件

自定义扫描路径:

java 复制代码
// 只扫描指定包
@SpringBootApplication(scanBasePackages = "com.example")

// 排除某些自动配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

3.2 Web层注解

java 复制代码
@RestController          // = @Controller + @ResponseBody,返回JSON
@Controller              // MVC控制器,返回视图名称
@RequestMapping("/api")  // 映射URL路径
@GetMapping("/users")    // GET请求映射
@PostMapping("/users")   // POST请求映射
@PutMapping("/{id}")     // PUT请求映射
@DeleteMapping("/{id}")  // DELETE请求映射

// 参数绑定注解
@PathVariable            // URL路径变量 /users/{id}
@RequestParam            // 查询参数 /users?page=1
@RequestBody             // 请求体JSON绑定
@RequestHeader           // 请求头绑定

3.3 依赖注入注解

java 复制代码
@Component      // 通用组件
@Service        // 业务层
@Repository     // 数据访问层
@Controller     // 控制层

@Autowired      // 按类型自动注入(字段注入,不推荐)
@RequiredArgsConstructor  // Lombok:构造器注入(推荐方式)
@Inject         // JSR-330标准注入

@Configuration  // 配置类
@Bean           // 配置类中定义Bean
@Scope          // Bean作用域(singleton/prototype/request/session)
@Conditional    // 条件装配

3.4 配置相关注解

java 复制代码
@ConfigurationProperties(prefix = "app.mail")  // 绑定配置文件属性
@Value("${app.name}")                          // 单个属性注入
@PropertySource("classpath:custom.properties") // 加载自定义配置文件
@Profile("dev")                                // 指定环境激活

四、自动配置原理

4.1 自动配置流程

Spring Boot的自动配置是其最核心的特性,整个流程如下:

复制代码
启动
  │
  ▼
@SpringBootApplication
  │
  ├─ @EnableAutoConfiguration
  │    │
  │    ▼
  │  Import AutoConfigurationImportSelector
  │    │
  │    ▼
  │  读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  │    │
  │    ▼
  │  获取所有候选自动配置类(约100+个)
  │    │
  │    ▼
  │  根据 @Conditional 条件过滤
  │    │
  │    ▼
  │  满足条件的配置类生效,注册对应的Bean
  │
  ▼
容器初始化完成

4.2 @Conditional条件注解族

注解 生效条件
@ConditionalOnClass 类路径中存在指定类
@ConditionalOnMissingClass 类路径中不存在指定类
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定Bean(最常用,方便用户覆盖)
@ConditionalOnProperty 配置文件中指定属性有指定值
@ConditionalOnResource 类路径下存在指定资源文件
@ConditionalOnWebApplication 当前是Web应用

4.3 源码解析:以DataSource自动配置为例

java 复制代码
@AutoConfiguration(before = SqlInitializationAutoConfiguration.class)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import(DataSourcePoolMetadataProvidersConfiguration.class)
public class DataSourceAutoConfiguration {

    // 嵌入式数据库(H2/HSQLDB/Derby)自动配置
    @Configuration(proxyBeanMethods = false)
    @Conditional(EmbeddedDatabaseCondition.class)
    @ConditionalOnMissingBean({DataSource.class, XADataSource.class})
    @Import(EmbeddedDataSourceConfiguration.class)
    protected static class EmbeddedDatabaseConfiguration {
    }

    // 连接池(HikariCP/Tomcat/DBCP2)自动配置
    @Configuration(proxyBeanMethods = false)
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({DataSource.class, XADataSource.class})
    @Import({DataSourceConfiguration.Hikari.class,
             DataSourceConfiguration.Tomcat.class,
             DataSourceConfiguration.Dbcp2.class})
    protected static class PooledDataSourceConfiguration {
    }
}

解读:

  1. 当类路径下存在 DataSource.class 时,自动配置才生效
  2. 如果容器中还没有用户自定义的 DataSource Bean,则自动创建
  3. 优先使用HikariCP连接池(Spring Boot默认)

4.4 手动覆盖自动配置

java 复制代码
@Configuration
public class CustomDataSourceConfig {

    // 自定义Bean会覆盖自动配置的Bean
    // 因为自动配置使用了 @ConditionalOnMissingBean
    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        ds.setUsername("root");
        ds.setPassword("secret");
        return ds;
    }
}

4.5 查看自动配置报告

启动时添加 --debug 参数或配置 debug=true

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

启动后控制台会输出自动配置报告:

复制代码
============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:(生效的自动配置)
-----------------
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource',
        'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'

Excluded exclusions:(被排除的)
--------------------
    None

Unconditional classes:(无条件生效的)
----------------------
    org.springframework.boot.autoconfigure.context...

五、配置文件详解

5.1 两种配置文件格式

Spring Boot支持两种配置文件格式:

application.properties(传统格式):

properties 复制代码
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
app.name=My Application
app.upload.max-size=10MB

application.yml(推荐,更清晰):

yaml 复制代码
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: 123456

app:
  name: My Application
  upload:
    max-size: 10MB

5.2 配置文件加载优先级

优先级 位置 说明
1(最高) file:./config/ 项目根目录的config子目录
2 file:./ 项目根目录
3 classpath:/config/ 类路径的config包
4(最低) classpath:/ 类路径根目录

高优先级配置会覆盖 低优先级配置,同时存在.properties.yml时,.properties优先。

5.3 自定义配置属性绑定

方式一:@Value 注入单个值

java 复制代码
@Component
public class AppInfo {

    @Value("${app.name}")
    private String appName;

    @Value("${app.version:1.0.0}")  // 带默认值
    private String version;

    @Value("${app.upload.max-size}")
    private String maxSize;
}

方式二:@ConfigurationProperties 批量绑定(推荐)

yaml 复制代码
# application.yml
app:
  mail:
    host: smtp.example.com
    port: 587
    username: admin@example.com
    password: secret
    protocol: smtp
    default-encoding: UTF-8
java 复制代码
@Data
@Component
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
    private String host;
    private int port;
    private String username;
    private String password;
    private String protocol;
    private String defaultEncoding;
}

启用@ConfigurationProperties的第二种方式------@EnableConfigurationProperties

java 复制代码
@Data
@ConfigurationProperties(prefix = "app.mail")  // 不加@Component
public class MailProperties {
    private String host;
    private int port;
}

// 在配置类中显式启用
@Configuration
@EnableConfigurationProperties(MailProperties.class)
public class MailConfig {
}

5.4 类型安全的属性校验

结合JSR-303验证注解:

java 复制代码
@Data
@Component
@ConfigurationProperties(prefix = "app.mail")
@Validated
public class MailProperties {

    @NotBlank(message = "邮件服务器地址不能为空")
    private String host;

    @Min(1)
    @Max(65535)
    private int port = 25;  // 默认值

    @Email
    private String username;

    @Pattern(regexp = "^(smtp|imap|pop3)$")
    private String protocol = "smtp";
}

5.5 复杂类型配置

yaml 复制代码
# application.yml
app:
  servers:
    - http://server1.example.com
    - http://server2.example.com
    - http://server3.example.com
  security:
    roles:
      admin: "管理员权限"
      user: "普通用户权限"
  upload:
    allowed-types:
      - image/png
      - image/jpeg
      - application/pdf
java 复制代码
@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private List<String> servers = new ArrayList<>();
    private Map<String, String> security = new HashMap<>();
    private Upload upload = new Upload();

    @Data
    public static class Upload {
        private List<String> allowedTypes = new ArrayList<>();
    }
}

六、多环境配置

6.1 多Profile文件

创建多个配置文件来管理不同环境:

复制代码
resources/
├── application.yml              # 公共配置
├── application-dev.yml          # 开发环境
├── application-test.yml         # 测试环境
├── application-staging.yml      # 预发布环境
└── application-prod.yml         # 生产环境

公共配置 application.yml

yaml 复制代码
app:
  name: My Application

spring:
  profiles:
    active: dev  # 默认激活的环境

开发环境 application-dev.yml

yaml 复制代码
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/dev_db
    username: dev_user
    password: dev_pass

logging:
  level:
    com.example: DEBUG

生产环境 application-prod.yml

yaml 复制代码
server:
  port: 80

spring:
  datasource:
    url: jdbc:mysql://prod-server:3306/prod_db
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

logging:
  level:
    com.example: WARN

6.2 激活Profile的多种方式

方式 示例 优先级
配置文件 spring.profiles.active=dev
命令行参数 --spring.profiles.active=prod 最高
JVM参数 -Dspring.profiles.active=prod
环境变量 SPRING_PROFILES_ACTIVE=prod
编程方式 SpringApplication.setAdditionalProfiles("dev") -
bash 复制代码
# 命令行指定
java -jar app.jar --spring.profiles.active=prod

# JVM参数指定
java -Dspring.profiles.active=prod -jar app.jar

# 多Profile同时激活
java -jar app.jar --spring.profiles.active=prod,ssl

6.3 Profile分组(Spring Boot 2.4+)

yaml 复制代码
spring:
  profiles:
    group:
      production: prod,metrics,logging
      staging: test,metrics

6.4 Profile条件装配

java 复制代码
@Configuration
public class DataSourceConfig {

    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        // 内嵌H2数据库
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://prod-server:3306/app");
        return ds;
    }
}

七、Starter机制

7.1 什么是Starter

Starter是Spring Boot提供的一组预定义依赖集合,引入一个Starter就能获得某个功能所需的全部依赖,且版本已经过官方兼容性测试。

7.2 常用Starter一览

Starter 用途 包含的主要依赖
spring-boot-starter-web Web开发 Spring MVC + Tomcat + Jackson
spring-boot-starter-data-jpa JPA数据访问 Hibernate + Spring Data JPA
spring-boot-starter-data-redis Redis Spring Data Redis + Lettuce
spring-boot-starter-security 安全框架 Spring Security
spring-boot-starter-test 测试 JUnit 5 + Mockito + AssertJ
spring-boot-starter-actuator 监控 Actuator端点
spring-boot-starter-mail 邮件发送 Spring Mail
spring-boot-starter-thymeleaf 模板引擎 Thymeleaf
spring-boot-starter-validation 参数校验 Hibernate Validator
spring-boot-starter-aop AOP切面 Spring AOP + AspectJ
spring-boot-starter-cache 缓存 Spring Cache
spring-boot-starter-amqp 消息队列 Spring AMQP (RabbitMQ)
spring-boot-starter-kafka Kafka Spring Kafka

7.3 Starter的工作原理

spring-boot-starter-web 为例,引入依赖后:

复制代码
spring-boot-starter-web
├── spring-boot-starter          # 核心Starter
│   ├── spring-boot              # Spring Boot核心
│   ├── spring-boot-autoconfigure # 自动配置
│   └── spring-core, spring-context, spring-beans...
├── spring-boot-starter-tomcat   # 内嵌Tomcat
│   ├── tomcat-embed-core
│   ├── tomcat-embed-el
│   └── tomcat-embed-websocket
├── spring-webmvc                # Spring MVC
├── jackson-databind             # JSON处理
└── spring-boot-starter-logging  # 日志(Logback)

不需要手动管理这些子依赖的版本号spring-boot-starter-parent已经统一管理。

7.4 自定义Starter

创建一个自定义Starter需要两个模块:

1. 自动配置模块:my-spring-boot-autoconfigure

java 复制代码
// 配置属性类
@Data
@ConfigurationProperties(prefix = "my.service")
public class MyServiceProperties {
    private String endpoint = "http://localhost:8080";
    private int timeout = 5000;
    private boolean enabled = true;
}

// 业务服务
public class MyService {
    private final MyServiceProperties properties;

    public MyService(MyServiceProperties properties) {
        this.properties = properties;
    }

    public String call() {
        return "Calling " + properties.getEndpoint() + " with timeout " + properties.getTimeout();
    }
}

// 自动配置类
@AutoConfiguration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyServiceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "my.service", name = "enabled", havingValue = "true",
                           matchIfMissing = true)
    public MyService myService(MyServiceProperties properties) {
        return new MyService(properties);
    }
}

2. 注册自动配置类(Spring Boot 3.x)

src/main/resources/META-INF/spring/ 目录下创建文件:

org.springframework.boot.autoconfigure.AutoConfiguration.imports

复制代码
com.example.autoconfigure.MyServiceAutoConfiguration

3. Starter模块:my-spring-boot-starter

xml 复制代码
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>my-spring-boot-autoconfigure</artifactId>
        <version>1.0.0</version>
    </dependency>
    <!-- 如果需要,还可以添加其他直接依赖 -->
</dependencies>

7.5 自定义Starter的最佳实践

规范 说明
命名 官方Starter:spring-boot-starter-xxx;第三方:xxx-spring-boot-starter
配置类 使用@ConfigurationProperties而非@Value
条件装配 充分利用@Conditional注解,提供覆盖能力
默认值 提供合理的默认值,做到零配置即可使用
文档 提供additional-spring-configuration-metadata.json支持IDE提示

八、Spring Boot生命周期与扩展点

8.1 启动流程

java 复制代码
public static void main(String[] args) {
    // 1. 创建SpringApplication实例
    SpringApplication app = new SpringApplication(DemoApplication.class);

    // 2. 设置自定义属性(可选)
    app.setBannerMode(Banner.Mode.OFF);
    app.setAdditionalProfiles("dev");

    // 3. 运行应用
    ConfigurableApplicationContext context = app.run(args);
}

8.2 常用扩展点

java 复制代码
// 1. ApplicationRunner:应用启动后执行
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("应用启动完成,执行初始化任务...");
        System.out.println("非选项参数: " + args.getNonOptionArgs());
        System.out.println("选项参数: " + args.getOptionNames());
    }
}

// 2. CommandLineRunner:应用启动后执行(接收原始参数)
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("命令行参数: " + Arrays.toString(args));
    }
}

// 3. 通过@Order控制执行顺序
@Component
@Order(1)  // 数字越小越先执行
public class FirstRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("第一个执行");
    }
}

// 4. EnvironmentPostProcessor:环境准备完成后、Bean创建前
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
                                        SpringApplication application) {
        // 可以在此添加/修改配置源
    }
}

// 5. BeanFactoryPostProcessor:Bean定义加载后、实例化前
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableBeanFactory beanFactory) {
        System.out.println("Bean定义数量: " + beanFactory.getBeanDefinitionCount());
    }
}

8.3 优雅关闭

yaml 复制代码
# application.yml
server:
  shutdown: graceful  # Spring Boot 2.3+

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s  # 等待时间
java 复制代码
@Component
public class GracefulShutdownHandler implements DisposableBean {
    @Override
    public void destroy() {
        System.out.println("应用即将关闭,执行清理工作...");
        // 释放资源、关闭连接池等
    }
}

九、常见面试题解析

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

答: Spring Boot通过@EnableAutoConfiguration注解开启自动配置。该注解导入了AutoConfigurationImportSelector,它会读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中的所有自动配置类。每个自动配置类都使用@Conditional系列注解进行条件判断,只有满足条件时才会生效。由于使用了@ConditionalOnMissingBean,用户自定义的Bean会优先覆盖自动配置的Bean。

Q2:@SpringBootApplication注解做了什么?

答: 它是三个注解的组合:

  • @SpringBootConfiguration:标记为配置类
  • @EnableAutoConfiguration:开启自动配置
  • @ComponentScan:扫描当前包及子包的组件

Q3:Spring Boot配置文件的加载优先级是怎样的?

答: 优先级从高到低:

  1. 命令行参数 --server.port=9090
  2. file:./config/ 目录
  3. file:./ 根目录
  4. classpath:/config/ 类路径config包
  5. classpath:/ 类路径根目录

高优先级覆盖低优先级,相同优先级时.properties覆盖.yml

Q4:Starter和普通依赖有什么区别?

答: Starter是一组相关依赖的集合,提供"开箱即用"的体验:

  • 统一管理版本兼容性
  • 引入一个Starter即可获得全部相关依赖
  • 配合自动配置,无需手动配置Bean
  • 普通依赖只是单一的库,需要自行管理版本和配置

Q5:如何自定义Starter?

答: 需要两个模块:

  1. xxx-spring-boot-autoconfigure:包含配置属性类、核心业务类和@AutoConfiguration标注的自动配置类
  2. xxx-spring-boot-starter:只引入autoconfigure模块的依赖
  3. META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中注册配置类

十、总结与下篇预告

本文小结

知识点 核心要点
Spring Boot定位 Spring的脚手架,约定优于配置
核心注解 @SpringBootApplication是三个注解的组合
自动配置 @EnableAutoConfigurationAutoConfigurationImportSelector@Conditional过滤
配置文件 .yml推荐,支持多Profile,@ConfigurationProperties批量绑定
多环境 Profile文件 + spring.profiles.active激活
Starter 一站式依赖 + 自动配置 = 开箱即用
自定义Starter @AutoConfiguration + @Conditional + @ConfigurationProperties

下篇预告

🔜 第39篇:Spring Boot Web实战------我们将深入Web开发,学习RESTful API设计、参数校验、统一响应封装、全局异常处理、拦截器以及Swagger接口文档生成,从零搭建一个企业级Web项目骨架!


📚 参考资料

  1. Spring Boot官方文档
  2. Spring Boot自动配置源码
  3. Spring Initializr
  4. Spring Boot Common Application Properties

💬 互动问题

  1. 你在项目中使用的是application.properties还是application.yml?为什么?
  2. 你有没有遇到过自动配置冲突的问题?是怎么解决的?
  3. 如果让你设计一个自定义Starter,你会为什么功能设计?

欢迎在评论区分享你的经验和想法!🚀

相关推荐
程序员老申1 小时前
外呼突然全挂了,追查 24 分钟后我发现了 etcd 最阴的一颗雷
后端·程序员
何以解忧,唯有..1 小时前
Go语言变量的声明方式详解
开发语言·后端·golang
长栎1 小时前
MyBatis 缓存为啥总是失效?装饰器模式套娃的代价
后端
bright_ye1 小时前
setjmp & longjmp 深度详解 + 代码示例
后端
To_OC1 小时前
我一直以为 Ajax 是个黑盒,直到我写了这 50 行代码
前端·后端·全栈
沪漂阿龙1 小时前
LangChain 系列:Structured Output结构化输出与源码解析
java·人工智能·架构·langchain
她的男孩1 小时前
AI 自动化编写 SQL 脚本,更要守住 Flyway 版本管理的防线
人工智能·后端
卷无止境1 小时前
Python的ABC库探索:能不能在系统设计之初就定义好所有抽象类?
后端
半夜燃烧的香烟1 小时前
springboot3.0 集成minio上传文件,支持多个桶名
java·开发语言·spring boot