一、Spring Initializer 快速创建 SpringBoot 项目

Spring Initializer 是 Spring 官方提供的项目初始化工具,也是企业、教学中标准、最快的SpringBoot项目搭建方式,无需手动建包、写配置、引依赖,一键生成可运行完整项目。

1.1 两种创建方式

方式1:在线官网创建(通用所有开发工具)

访问 Spring 官方初始化地址,按需配置参数、选择依赖,一键下载项目压缩包,导入IDEA即可使用。

方式2:IDEA内置Initializer创建(主流首选)

新版IDEA已内置Spring Initializer,无需访问网页,直接本地可视化创建,支持实时选择版本、依赖,是目前开发、教学通用方式。

1.2 标准创建流程(零基础复刻)

  1. 打开IDEA,选择 New Project - Spring Initializr(新版为Spring boot)

  2. 配置项目基础信息:Group、Artifact、Java版本(SpringBoot3.x 强制JDK17+);

  3. 选择 SpringBoot 版本:3.3.x 长期支持版(稳定企业版);

  4. 勾选所需依赖:日常开发首选 Spring Web(Web开发必备,如果是父类项目可以不选)、Configuration Processor(配置绑定提示);

  5. 点击创建,IDEA自动联网生成完整项目,包含启动类、配置文件、标准目录结构。

1.3 初始化项目标准目录结构(核心必懂)

Initializer 自动生成规范目录,每个文件夹作用固定,遵循SpringBoot约定大于配置核心思想:

  • src/main/java:业务代码存放目录,自动生成项目启动主类

  • src/main/resources:核心资源与配置目录

    • static:存放静态资源(js、css、图片等)

    • templates:存放模板页面(配合thymeleaf、freemarker模板引擎,SpringBoot默认不支持JSP)

    • application.yml / application.properties:SpringBoot全局核心配置文件,修改框架默认配置、自定义业务参数

  • pom.xml:自动管理依赖版本,无需手动适配版本冲突

1.4 自定义 SpringApplication 启动配置

Initializer 生成的默认启动规则可自定义改造,通过原生API修改启动横幅、运行参数等,支持两种写法:

常规写法:

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(DemoApplication.class);
    // 关闭启动横幅
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
}

流式构造写法(简洁优雅):

new SpringApplicationBuilder()
        .bannerMode(Banner.Mode.OFF)
        .run(args);

二、SpringBoot 核心配置文件详解

通过 Initializer 创建的项目会自动生成全局配置文件,配置文件的核心作用:覆盖SpringBoot自动配置的默认值,自定义项目运行参数,是连接开发者与自动配置的核心桥梁。

2.1 两种配置文件格式

SpringBoot 支持两种全局配置文件,文件名固定、优先级版本适配新版规范:

  • application.properties:扁平 key-value 格式,结构简单,可读性差,老旧项目常用

  • application.yml / application.yaml:树形层级格式,简洁直观、可读性强

格式对比实战

properties 写法:

server.port=8088
server.servlet.context-path=/demo

yml 写法(层级对应,更贴合代码结构):

server:
  port: 8088
  servlet:
    context-path: /demo

yml语法硬性规范:冒号后必须加空格、靠缩进控制层级、大小写敏感,特殊字符需单引号包裹,语法错误直接导致项目启动失败。官方建议:全程统一一种配置格式,避免版本优先级混乱

2.2 yml全类型语法大全

支持所有日常配置类型,新手可直接复用:

# 1.字面量(字符串、数字、布尔)
name: springboot3
age: 20
isOpen: true

# 2.对象/Map配置
user:
  username: admin
  password: 123456

# 3.数组/List配置
hobby:
  - 编程
  - 学习
  - 运动

# 行内精简写法
map: {k1: v1, k2: v2}
list: [a,b,c]

2.3 配置文件占位符高级用法

支持随机数生成、配置引用、默认值兜底,适配动态配置场景:

# 随机参数
random:
  uuid: ${random.uuid}
  num: ${random.int(10,100)}

# 配置引用+默认值
person:
  name: 测试用户${random.uuid}
  desc: ${person.info:默认描述信息}

三、配置文件加载优先级与多环境Profile

3.1 配置文件全局加载顺序

SpringBoot 启动时会自动扫描4个位置的配置文件,遵循高优先级覆盖低优先级、互补配置原则,优先级从低到高:

  1. 项目内部 resources 根目录

  2. 项目内部 resources/config 目录

  3. 项目根目录外部配置

  4. 项目根目录 config 外部配置

最终最高优先级:命令行参数、系统环境变量、自定义外部配置,可覆盖所有文件配置。

3.2 多环境Profile配置(dev/test/prod)

开发、测试、生产环境参数不同,通过Profile实现环境隔离,命名规范固定:application-{环境}.yml

  • application-dev.yml:开发环境配置

  • application-test.yml:测试环境配置

  • application-prod.yml:生产环境配置

环境激活两种方式

1、配置文件激活(开发常用):

spring:
  profiles:
    active: dev

2、命令行激活(生产部署常用):

java -jar demo.jar --spring.profiles.active=prod

3.3 配置文件读取方式 & 官方完整13级加载优先级(从低到高|课程原版)

本节完全依据 SpringBoot 官方源码机制与课程文档整理,完整列出 13种配置读取方式,严格按照 优先级从低到高 排序。核心规则:低优先级先加载、高优先级后加载;同名配置高优先级覆盖低优先级,不同配置相互互补

所有配置分为:代码自定义配置 → 本地约定配置文件 → 系统环境配置 → 容器/命令行动态配置 → 测试专属配置

3.3.1 优先级1:@PropertySource 自定义外部配置(最低优先级)

核心特点:自定义加载properties配置文件,仅补充配置,无法覆盖系统级默认配置;在容器刷新前不会加载,部分前置核心配置(spring.main、logging.*)无法通过该方式修改。

注意:仅支持 .properties 文件,不支持yml文件。

代码实例
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource("classpath:appSource.properties")
public class AppConfig {
    // 读取自定义配置文件参数
}
适用场景

项目自定义拓展配置、拆分业务配置,不改动原生application核心配置,做参数补充。

3.3.2 优先级2:SpringApplication.setDefaultProperties 默认属性

核心特点:代码硬编码设置项目默认配置,优先级高于@PropertySource,低于所有约定配置文件,用于设置项目兜底默认参数。

代码实例
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
import java.util.Properties;

@SpringBootApplication
public class ConfigApplication {
    public static void main(String[] args) throws IOException {
        SpringApplication application = new SpringApplication(ConfigApplication.class);
        // 加载自定义properties配置
        Properties properties = new Properties();
        properties.load(ConfigApplication.class.getClassLoader().getResourceAsStream("app.properties"));
        // 设置项目默认配置
        application.setDefaultProperties(properties);
        application.run(args);
    }
}
适用场景

设置项目全局兜底默认值,当配置文件缺失参数时,自动生效补齐。

3.3.3 优先级3:系统约定配置文件(application.yml/properties)

核心特点:SpringBoot 原生约定配置,包含 resources、resources/config、外部根目录、外部config目录所有默认配置文件,是项目核心业务配置载体。

规则:覆盖前两级自定义配置,被后续系统环境、命令行配置覆盖。

适用场景

日常开发90%配置写入位置,存放项目端口、数据库、中间件、业务参数等核心配置。

3.3.4 优先级4:操作系统环境变量

核心特点:读取服务器、操作系统、Docker/K8s容器环境变量,会使低级约定配置同名参数失效,优先级高于所有本地配置文件。

实战方式
  • Windows:cmd执行 set spring.config.location=D:\config/

  • Linux/Mac:终端export设置环境变量

  • Docker/K8s:容器环境变量注入配置

适用场景

容器化部署、多服务器差异化配置、线上环境保密参数配置。

3.3.5 优先级5:Java系统属性 System.getProperties()

核心特点:通过JVM参数传递配置,优先级高于系统环境变量,可覆盖本地配置文件。

命令行实例
# -D 传递JVM系统属性,指定外部配置文件位置
java -Dspring.config.location=D:\config\application-java.properties -jar demo.jar
适用场景

启动时临时修改全局JVM级配置、线上动态替换配置文件。

3.3.6 优先级6:JNDI属性(java:comp/env)

核心特点:JavaEE容器专属属性,用于Tomcat容器资源配置,优先级高于Java系统属性,企业项目极少使用。

适用场景

传统JavaEE Web项目、外置容器资源绑定配置。

3.3.7 优先级7:ServletContext 初始化参数

核心特点:全局Web上下文配置,在web-app根标签中配置,作用于整个Web项目。

配置实例
<!-- web.xml 配置 -->
<context-param>
    <param-name>spring.config.location</param-name>
    <param-value>xxx.properties</param-value>
</context-param>
适用场景

传统SSM+SpringBoot混合Web项目、全局Web配置统一指定。

3.3.8 优先级8:ServletConfig 初始化参数

核心特点:单个Servlet专属配置,仅作用于指定Servlet,优先级高于ServletContext。

配置实例
<!-- web.xml 对应servlet标签内配置 -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>spring.config.location</param-name>
        <param-value>xxx.properties</param-value>
    </init-param>
</servlet>
适用场景

需要单独为某个Servlet定制专属配置的传统Web项目。

3.3.9 优先级9:SPRING_APPLICATION_JSON 嵌入式JSON配置

核心特点:嵌入在环境变量或系统属性中的JSON格式配置,优先级高于Web容器配置,是SpringBoot高级动态配置方式。

适用场景

云原生项目、极简动态传参、复杂结构化动态配置传递。

3.3.10 优先级10:命令行启动参数(--key=value)

核心特点:生产最常用动态配置,覆盖所有静态配置、环境变量、系统属性,优先级极高。

命令行实例
# 启动jar时动态指定外部配置文件,覆盖所有原有配置
java -jar demo.jar --spring.config.location=D:/application.properties
适用场景

线上紧急改参、CI/CD自动化部署、多环境动态切换、无需重打包更新配置。

3.3.11 优先级11:测试环境 Properties 测试参数

核心特点:@SpringBootTest 单元测试内置配置参数,仅测试环境生效,不影响生产环境。

适用场景

单元测试临时定制参数、测试环境隔离配置。

3.3.12 优先级12:@TestPropertySource 测试专属配置

核心特点:单元测试专属注解,加载测试自定义配置文件,优先级高于所有主程序配置。

代码实例
import org.springframework.test.context.TestPropertySource;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@TestPropertySource("classpath:appSource.properties")
public class ConfigTest {
    // 测试类专属配置,独立生效
}
适用场景

单元测试需要隔离测试环境、独立测试参数,不污染主项目配置。

3.3.13 优先级13:Devtools 全局开发配置(最高优先级)

核心特点:开发者工具生效时,加载 $HOME/.config/spring_boot 目录全局配置,全局最高优先级,仅开发环境生效,生产无效。

适用场景

本地开发统一全局dev配置、团队统一开发环境默认参数。


3.3.14 完整官方优先级总表(从低 → 高|完整版)

  1. @PropertySource 自定义properties配置文件

  2. SpringApplication.setDefaultProperties 代码默认属性

  3. 项目约定application配置文件(本地/resources/外部config等)

  4. 操作系统环境变量

  5. Java系统属性(-D参数)

  6. JNDI属性 java:comp/env

  7. ServletContext 全局初始化参数

  8. ServletConfig 单个Servlet初始化参数

  9. SPRING_APPLICATION_JSON 嵌入式JSON配置

  10. 命令行启动参数(--xxx)

  11. @SpringBootTest 测试内置属性

  12. @TestPropertySource 测试自定义配置

  13. Devtools 开发工具全局配置(开发环境最高)

3.3.15 核心规则总结

  • 互补覆盖规则:同名配置高优先级覆盖低优先级,不同配置全部互补生效;

  • 动态覆盖静态:命令行、环境变量、JVM参数等动态配置,优先覆盖本地静态配置文件;

  • 测试隔离规则:所有测试相关配置仅测试环境生效,不会污染生产环境;

  • 开发最高原则:Devtools配置仅本地开发生效,是所有场景中优先级最高的配置;

  • 注解限制:@PropertySource 无法加载yml、无法覆盖前置框架核心配置。


SpringBoot 提供多位置、多方式、动态优先级配置读取机制,核心规则:先加载低优先级配置,再加载高优先级配置,高优先级参数会覆盖低优先级同名参数;不同配置参数互补共存。本节整理官方最全读取位置,严格按照优先级从低到高 排序,适配 SpringBoot3.x 最新规范。

优先级口诀:内部根目录 < 内部config < 项目根外部 < 项目config外部 < 系统环境变量 < 命令行参数


四、配置文件值注入Bean(两种核心方式)

将配置文件参数绑定到Java实体类,实现配置与代码解耦,是项目实例创建的基础。

4.1 @Value(单值零散注入)

适合少量参数获取,支持SpEL表达式运算:

@Component
public class ConfigDemo {
    @Value("${person.name}")
    private String name;
    @Value("#{10*2}")
    private Integer num;
}

4.2 @ConfigurationProperties(批量绑定,企业首选)

适合批量绑定对象、集合,支持松散绑定、配置提示、参数校验,是类继承实例创建的核心注解。

需先导入配置处理器依赖(Initializer可直接勾选):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

4.3 两种注入方式核心区别

对比项

@Value

@ConfigurationProperties

注入方式

单个逐一注入

批量前缀绑定

松散绑定

不支持

支持(userName / user-name / user_name 通用)

SpEL表达式

支持

不支持

适用场景

少量零散参数

批量业务配置、实例绑定


五、基于类继承的项目实例创建(核心实战)

依托上述配置绑定能力,SpringBoot支持父类通用模板 + 子类差异化扩展的继承式实例创建,彻底解决多模块配置代码冗余问题,是企业标准化开发核心用法。

5.1 核心原理

  • 公共父类:封装所有业务通用配置、校验规则,仅作为模板,不交给Spring托管

  • 业务子类:继承父类,自动复用通用属性,扩展独有业务字段,绑定配置文件,Spring自动创建完整Bean实例

5.2 完整实战流程

步骤1:定义通用配置父类

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;

// 公共配置父类:所有业务子类继承复用
public class BaseServiceConfig {
    // 通用属性
    private String name;
    @Min(1000)
    @Max(10000)
    private Integer timeout;
    private Boolean enableLog;

    // 通用get/set
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getTimeout() { return timeout; }
    public void setTimeout(Integer timeout) { this.timeout = timeout; }
    public Boolean getEnableLog() { return enableLog; }
    public void setEnableLog(Boolean enableLog) { this.enableLog = enableLog; }
}

步骤2:定义业务子类(继承扩展)

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import org.springframework.stereotype.Component;

// 订单业务配置子类,继承通用父类
@Component
@ConfigurationProperties(prefix = "business.order")
@Validated
public class OrderServiceConfig extends BaseServiceConfig {
    // 子类独有属性
    private Integer maxRetry;
    private String orderPrefix;

    public Integer getMaxRetry() { return maxRetry; }
    public void setMaxRetry(Integer maxRetry) { this.maxRetry = maxRetry; }
    public String getOrderPrefix() { return orderPrefix; }
    public void setOrderPrefix(String orderPrefix) { this.orderPrefix = orderPrefix; }
}

步骤3:配置文件绑定参数

business:
  order:
    # 继承父类通用属性
    name: 订单业务服务
    timeout: 4000
    enable-log: true
    # 子类独有属性
    max-retry: 3
    order-prefix: ORDER_

步骤4:注入使用继承实例

import org.springframework.stereotype.Service;

@Service
public class OrderBusinessService {
    // 直接注入完整继承实例
    private final OrderServiceConfig orderConfig;

    public OrderBusinessService(OrderServiceConfig orderConfig) {
        this.orderConfig = orderConfig;
    }

    public void printConfig() {
        // 父类继承属性
        System.out.println("服务名称:" + orderConfig.getName());
        // 子类独有属性
        System.out.println("订单前缀:" + orderConfig.getOrderPrefix());
    }
}

5.3 核心优势与规范

  • 代码极致复用,多模块无需重复编写通用配置

  • 父类统一校验规则,全局配置规范统一

  • 子类独立绑定配置前缀,实例互不冲突、差异化灵活


六、基于 Maven Parent 父工程继承创建多模块项目(工程级继承)

前面第五章讲解的是代码类级别的继承(Java子类继承父类实现配置复用),本章重点讲解企业真实多模块架构:Maven 工程级继承

在 SpringBoot 微服务/多模块项目中,通过 pom.xml 的 <parent> 标签引入统一父工程,让所有子模块继承父工程的版本管理、依赖、插件、统一配置,实现一键标准化创建多子项目,是企业项目规范搭建的核心标准方式。

6.1 核心概念:Parent 父工程继承

Maven 继承分为两层核心逻辑,也是 SpringBoot 项目的底层构建基础:

  • SpringBoot 官方父工程:所有 SpringBoot 项目默认继承 spring-boot-starter-parent,统一框架依赖版本、编译插件、默认编码、打包规则

  • 自定义项目父工程:企业自建 Parent 工程,所有业务子模块继承该工程,统一项目内部依赖版本、公共依赖、自定义属性、环境配置

核心作用:父工程统一管控,子模块零配置继承,快速批量创建规范子项目,彻底解决版本混乱、依赖冗余问题

6.2 工程继承整体架构

标准三层继承架构(企业通用):

  1. 第一层:SpringBoot 官方父工程:提供框架底层统一版本管控

  2. 第二层:自定义项目 Parent 父工程:继承官方父工程,定义项目全局统一依赖、版本、插件、属性

  3. 第三层:业务子模块:用户模块、订单模块、支付模块等,通过 <parent> 继承自定义父工程,无需重复配置

6.3 实战:通过 <parent> 实现项目继承创建多模块

本实战基于 Spring Initializer 创建的标准项目改造,从零实现父工程 + 多个子模块的继承架构。

步骤1:创建自定义 Parent 父工程

首先创建一个空 Maven 工程作为项目全局父工程,打包方式必须为 pom,仅用于统一管理,无业务代码。

父工程 pom.xml 核心配置:继承 SpringBoot 官方父工程,统一全局版本与依赖

<?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>

    <!-- 1、继承SpringBoot官方父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/>
    </parent>

<!-- 2、当前自定义父工程坐标 -->
    <groupId>com.example</groupId>
    <artifactId>boot-parent</artifactId>
    <version>1.0.0</version>
    <name>全局父工程</name>
    <description>统一项目版本与依赖管理父工程</description>
    <packaging>pom</packaging>

   <!-- 3、全局统一版本属性 -->
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <mybatis.version&gt;3.0.3&lt;/mybatis.version&gt;
    &lt;/properties&gt;

    <!-- 4、统一依赖版本管理(子模块自动继承) -->
    <dependencyManagement>
        <dependencies>
            <!-- 统一web依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
<!-- 统一配置处理器依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
        </dependencies>
    &lt;/dependencyManagement&gt;

    <!-- 5、统一编译、打包插件 -->
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

步骤2:创建业务子模块,通过 <parent> 继承父工程

在父工程下创建多个业务子模块(user、order、pay),所有子模块无需定义版本、无需重复引入公共依赖,直接通过 <parent> 继承全局配置。

子模块 pom.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>com.example</groupId>
        <artifactId>boot-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent&gt;

    <!-- 子模块唯一标识,无需写version,自动继承父工程 -->
    <artifactId>boot-user</artifactId>
    &lt;name&gt;用户模块子项目&lt;/name&gt;

    <!-- 仅引入当前模块独有依赖,公共依赖全部继承 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

步骤3:快速批量创建多个子模块

按照上述子模块配置,可快速创建 order订单模块、pay支付模块、log日志模块 等多个子项目:

  • 所有子模块版本统一、编译环境统一、公共依赖统一

  • 新增模块只需新建子工程、绑定parent继承,无需重复配置基础环境

  • 父工程统一管控,全局依赖版本一键升级、统一修改

6.4 Maven Parent 工程继承核心机制

  • 版本继承:子模块无需指定 version,自动继承父工程版本,全局版本统一

  • 依赖继承:父工程 dependencyManagement 声明的依赖,子模块可直接引用、无需写版本

  • 插件继承:编译、打包插件全局统一,所有子模块打包、编译规则一致

  • 属性继承:编码格式、JDK版本、自定义变量全局统一,避免环境不一致

6.5 基于 <parent> 项目继承的优缺点

✅ 核心优点

  • 版本统一,杜绝冲突:所有子模块继承父工程版本管控,彻底解决多模块依赖版本不一致、Jar包冲突问题

  • 极大简化子模块配置:子项目pom极简,无需重复编写公共依赖、插件、JDK配置,开发效率大幅提升

  • 全局统一规范:编码格式、编译规则、打包方式、依赖管理全局统一,项目规范性极强

  • 迭代维护方便:框架升级、依赖版本更新只需修改父工程,所有子模块一键同步生效

  • 快速批量建模块:新增业务模块无需搭建基础环境,继承parent即可快速成型,适配微服务多模块架构

❌ 核心缺点

  • 耦合度较高:子模块强依赖父工程,父工程配置出错、版本冲突会导致所有子项目全部报错

  • 版本灵活性差:全局统一版本,若个别子模块需要特殊版本依赖,需要单独重写覆盖,配置繁琐

  • 父工程维护成本高:随着项目迭代,父工程依赖越来越多,容易出现冗余依赖、无效依赖堆积

  • 单继承限制:Maven 仅支持单父继承,一个子项目只能继承一个父工程,无法实现多工程继承组合

6.6 工程继承 VS 代码类继承(核心区别)

继承方式

继承层级

作用范围

核心用途

Maven Parent 工程继承

Pom 工程层级

整个项目模块

统一版本、依赖、插件、环境配置,批量创建规范子项目

Java 类继承

代码类层级

单个业务Bean实例

复用代码属性、校验规则,实现业务实例差异化扩展

6.7 企业开发使用规范

  • 大型多模块、微服务项目:必须使用 Parent 父工程继承,统一项目基建规范

  • 父工程只做版本声明与依赖管理,不引入具体业务依赖,避免依赖冗余

  • 特殊模块需要差异化版本时,在子模块局部覆盖,不改动全局父工程

  • 结合代码类继承 + 工程继承,实现项目架构+业务代码双层复用,是企业最优方案

七、SpringBoot 自动配置核心原理

SpringBoot 核心精髓为 约定大于配置、自动装配,摒弃SSM繁琐的XML配置、手动Bean注册流程,项目启动时自动加载框架预置配置类、注册核心组件、绑定默认参数。

7.1 核心入口:@SpringBootApplication 启动复合注解

SpringBoot项目唯一启动注解,是组件扫描+自动配置的集合入口,由三层核心注解复合组成,每一层各司其职,共同完成项目初始化装配。

@SpringBootApplication 底层三大核心注解

  • @SpringBootConfiguration:标识当前类为SpringBoot配置类,底层基于@Configuration实现,允许通过@Bean注册组件,替代传统spring.xml配置文件

  • @ComponentScan:自动扫描当前启动类所在包及子包下所有带@Component、@Controller、@Service、@Repository的组件,自动纳入IOC容器管理,无需手动配置扫描路径

  • @EnableAutoConfiguration自动配置核心开关,开启SpringBoot自动装配功能,是整个自动配置原理的核心关键注解

7.2 核心关键:@EnableAutoConfiguration 底层源码机制

该注解是SpringBoot自动配置的灵魂,底层依靠两个注解完成自动配置类扫描、加载、注册,完全贴合课程文档源码逻辑。

7.2.1 底层两大子注解

  1. @AutoConfigurationPackage 作用:自动记录、保存启动类所在包路径,提供给SpringDataJPA、组件扫描等底层功能使用,固定项目扫描根路径,保证包扫描不越界、不遗漏。

  2. @Import(AutoConfigurationImportSelector.class) 作用:自动配置核心实现类,通过该选择器类扫描所有自动配置类,加载预置组件,是自动配置的核心入口方法。

7.2.2 核心源码流程(课程原版)

项目启动执行 SpringApplication.run() 后,底层触发 getAutoConfigurationEntry() 方法,完整执行流程如下:

  1. 校验当前自动配置功能是否开启,未开启则直接返回空配置;

  2. 读取注解属性,获取需要排除的自动配置类;

  3. 扫描所有jar包中 META-INF/spring.factories 文件(核心步骤);

  4. 加载文件中 key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的所有自动配置类全限定类名;

  5. 去重、过滤、排除指定配置类,得到最终生效的自动配置类集合;

  6. 将合法自动配置类导入Spring容器,完成自动装配。

核心知识点: 所有SpringBoot自动配置类、底层组件配置,全部定义在 spring-boot-autoconfigure 依赖包的 spring.factories 文件中,项目引入该依赖即可拥有全套自动配置能力。

7.3 自动配置类本质:XXXAutoConfiguration 配置类

SpringBoot底层所有自动配置,本质都是一个个被@Configuration标注的Java配置类,命名规范统一为 XXXAutoConfiguration,例如:

  • HttpEncodingAutoConfiguration:请求编码自动配置

  • WebMvcAutoConfiguration:Web框架自动配置

  • DataSourceAutoConfiguration:数据库数据源自动配置

  • ServerAutoConfiguration:服务器端口、容器自动配置

7.3.1 自动配置类标准结构(以编码配置为例)

所有自动配置类遵循统一模板,包含配置注解、属性绑定、条件注解、组件注册四大核心部分,贴合课程案例:

@Configuration(proxyBeanMethods = false)
// 绑定配置文件中server.servlet.encoding前缀的配置参数
@EnableConfigurationProperties(ServerProperties.class)
// 条件注解:满足环境条件当前配置类才生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    // 注入绑定好的配置属性类
    private final ServerProperties properties;

    // 构造器绑定配置参数
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    // 条件缺失Bean才注册,避免覆盖用户自定义组件
    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        // 从配置文件读取编码格式
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
        return filter;
    }
}

7.4 两大核心配套注解(自动配置核心支撑)

7.4.1 @EnableConfigurationProperties 属性绑定注解

核心作用:开启配置文件与实体类的绑定功能,将 application.yml/properties 中的配置参数,自动绑定到XXXProperties属性类中,让自动配置类可以读取用户自定义配置,实现默认配置+用户自定义配置覆盖的能力。

核心逻辑:自动配置类不写死参数,全部从属性类读取,用户可通过配置文件修改框架默认值。

7.4.2 @Conditional 系列条件注解(重中之重)

SpringBoot 按需装配核心机制:自动配置类默认加载,但必须满足指定条件才会生效、注册Bean,避免无效组件加载、减少项目资源占用,是自动配置智能化的关键。

课程原版全套条件注解对照表:

条件注解

生效条件(核心释义)

@ConditionalOnJava

当前JDK版本匹配指定版本时生效

@ConditionalOnBean

容器中存在指定Bean实例时生效

@ConditionalOnMissingBean

容器中不存在指定Bean时生效(用户自定义优先)

@ConditionalOnClass

项目中存在指定Class类文件时生效

@ConditionalOnMissingClass

项目中不存在指定Class类文件时生效

@ConditionalOnWebApplication

当前为Web项目环境时生效

@ConditionalOnNotWebApplication

当前非Web项目环境时生效

@ConditionalOnProperty

配置文件中指定参数匹配时生效

@ConditionalOnResource

项目中存在指定资源文件时生效

@ConditionalOnExpression

SpEL表达式结果为true时生效

@ConditionalOnJndi

存在指定JNDI资源时生效

面试高频考点: @ConditionalOnMissingBean 是用户自定义优先原则的核心!SpringBoot默认组件仅在用户未自定义时生效,用户手动注册Bean后,自动配置组件失效,实现灵活覆盖。

7.5 XXXProperties 属性绑定类原理

所有可配置的框架参数,都对应一个属性配置类,以ServerProperties、DataSourceProperties为代表,核心作用:

  1. 通过@ConfigurationProperties绑定配置文件指定前缀的所有参数;

  2. 定义参数默认值,用户未配置时使用框架默认值;

  3. 为自动配置类提供可读取的配置参数,实现配置文件动态修改框架行为。

核心结论配置文件能写什么参数,完全由XXXProperties类中的属性决定,所有SpringBoot可配置参数均可在对应属性类中查阅。

7.6 自动配置生效查看方式(调试必备)

通过配置文件开启自动配置报告,可精准查看哪些自动配置生效、哪些失效、失效原因

7.6.1 开启调试报告

# 开启自动配置调试日志
debug: true

7.6.2 日志核心分类

  • Positive matches(正向匹配):自动配置类条件满足,已生效,成功注册组件

  • Negative matches(反向匹配):条件不满足,未生效,标注具体失效原因

  • Unconditional classes:无条件生效的核心基础配置类

7.7 自动配置完整执行链路

结合全文源码与课程文档,梳理SpringBoot启动自动配置完整闭环流程

  1. 项目启动,执行 SpringApplication.run() 方法;

  2. 启动类上 @SpringBootApplication 生效,触发@EnableAutoConfiguration;

  3. 通过@Import导入AutoConfigurationImportSelector核心选择器;

  4. 扫描所有jar包spring.factories文件,加载全部自动配置类;

  5. 过滤、去重、排除指定配置,筛选合法配置类;

  6. 读取每个配置类上的@Conditional条件注解,按需装配;

  7. 通过@EnableConfigurationProperties绑定配置文件参数;

  8. 满足条件的配置类通过@Bean注册核心组件至IOC容器;

  9. 用户自定义Bean优先覆盖自动配置Bean,完成最终装配。

7.8 自动配置核心规则

  • 约定优先,配置覆盖:框架提供默认约定配置,用户可通过yml/properties配置文件自定义覆盖;

  • 按需装配,条件生效:所有自动配置类依靠条件注解判断,不满足条件不加载,轻量化启动;

  • 用户自定义优先:@ConditionalOnMissingBean保证用户手动定义的Bean优先生效,框架自动Bean兜底;

  • 配置解耦分离:自动配置类负责组件注册,Properties类负责参数绑定,职责单一、解耦清晰;

  • 零配置开箱即用:无需XML、无需手动注册核心组件,引入依赖即可自动完成环境装配。

7.9 手动关闭指定自动配置(拓展实战)

若需要禁用某一自动配置类,可通过启动注解排除,解决配置冲突问题:

// 排除数据源自动配置、WebMvc自动配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, WebMvcAutoConfiguration.class})
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

更多推荐