spring boot faq

what are spring boot features?

  • Create stand-alone Spring applications

  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

  • Provide opinionated ‘starter’ dependencies to simplify your build configuration

  • Automatically configure Spring and 3rd party libraries whenever possible

  • Provide production-ready features such as metrics, health checks, and externalized configuration

  • Absolutely no code generation and no requirement for XML configuration

what the usage of @ConfigurationProperties and @ConfigurationPropertiesScan?

@ConfigurationProperties 和 @ConfigurationPropertiesScan 是 Spring Boot 中用于加载和管理外部配置的注解。它们的主要作用是将外部配置文件(如 application.properties 或 application.yml)中的配置映射到 Java 类中,从而简化配置管理。

  1. @ConfigurationProperties

@ConfigurationProperties 用于将配置文件中的一组相关配置映射到一个 Java 类的字段中。

用法

  1. 创建一个 Java 类,并添加 @ConfigurationProperties 注解,指定配置前缀。

  2. 在 Spring 上下文中注册该类,使其成为一个 Bean。

示例

application.yml:

app:
  name: MyApp
  version: 1.0
  description: This is a sample application.

配置类:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;
    private String description;

    // Getters and setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

使用配置类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AppController {
    private final AppConfig appConfig;

    @Autowired
    public AppController(AppConfig appConfig) {
        this.appConfig = appConfig;
    }

    @GetMapping("/info")
    public String getAppInfo() {
        return "App Name: " + appConfig.getName() + 
               ", Version: " + appConfig.getVersion() + 
               ", Description: " + appConfig.getDescription();
    }
}

特点

  • 类型安全:通过 Java Bean 的字段类型,确保配置值的正确性。

  • 支持嵌套:可以通过嵌套类表示更复杂的配置结构。

  • 支持校验:结合 @Validated 和 JSR 303 注解(如 @NotNull、@Min)校验配置值。

  1. @ConfigurationPropertiesScan

@ConfigurationPropertiesScan 是用于扫描并注册 @ConfigurationProperties 标注的类为 Spring Bean 的注解。

用法

  • 默认情况下,@ConfigurationProperties 标注的类需要使用 @Component 或者通过 @Bean 显式注册。

  • @ConfigurationPropertiesScan 可以自动扫描指定包下的所有 @ConfigurationProperties 类,无需额外标注 @Component。

示例

将上述 AppConfig 类移除 @Component:

配置类:

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;
    private String description;

    // Getters and setters
}

启动类:

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@ConfigurationPropertiesScan
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}

特点

  • 减少注解冲突:无需在每个配置类上添加 @Component,只需要 @ConfigurationProperties。

  • 自动扫描:通过 @ConfigurationPropertiesScan 自动扫描 @ConfigurationProperties 类所在的包及其子包。

两者的主要区别

特性

@ConfigurationProperties

@ConfigurationPropertiesScan

作用

将配置映射到 Java 类

自动扫描并注册所有 @ConfigurationProperties 类

需要额外注解

通常需要搭配 @Component 或 @Bean

无需额外注解,自动扫描

配置注册方式

手动注册

自动扫描,减少样板代码

推荐使用场景

  1. 简单配置类:直接用 @ConfigurationProperties + @Component。

  2. 多个配置类或复杂配置:用 @ConfigurationPropertiesScan 简化管理,避免逐个注册配置类。

注意事项

  • @ConfigurationProperties 类的字段必须有 getter 和 setter 方法。

  • 必须确保 Spring Boot 的 spring-boot-configuration-processor 依赖已添加,才能在编译时生成元数据文件,支持 IDE 的代码补全功能。

依赖(build.gradle 或 pom.xml): `` dependencies { annotationProcessor ‘org.springframework.boot:spring-boot-configuration-processor’ }



## 配置属性有哪几种方式, 各自的优先级如何?

在 Spring Boot 中,配置属性的优先级决定了当同一属性通过不同方式定义时,哪种方式的值最终生效。Spring Boot 按以下优先级从高到低解析配置属性:

Spring Boot 配置属性优先级(从高到低)

 1. 命令行参数
  * 通过 JVM 启动时提供的命令行参数指定属性值,例如:

java -jar app.jar --server.port=8081


  * 或直接使用 -D 方式设置 JVM 属性:

java -Dserver.port=8081 -jar app.jar


 2. @TestPropertySource 注解
  * 测试类中使用 @TestPropertySource 指定的属性优先级高于默认配置。
 3. @SpringBootTest 中的属性
  * 在 @SpringBootTest 注解中通过 properties 属性指定的值。
 4. Java 系统属性
  * JVM 属性设置,例如:

java -Dserver.port=8081 -jar app.jar


 5. 操作系统环境变量
  * 设置为环境变量的属性,例如:

export SERVER_PORT=8081


 6. RandomValuePropertySource
  * 生成的随机值(如 ${random.int})会在程序运行时动态注入。
 7. 应用配置文件 (application.properties 或 application.yml)
  * 包含以下几类:
  * 配置文件位置高优先级(外部配置文件优先于内部文件):
  * file:./config/ (项目根目录 config 文件夹)
  * file:./ (项目根目录)
  * classpath:/config/ (类路径下 config 文件夹)
  * classpath:/ (类路径根目录)
  * 如果多个文件存在且设置相同属性,按加载顺序取优先级最高的值。
  * application-{profile}.properties 文件优先级高于 application.properties。
 8. 默认配置文件 application.properties 或 application.yml 中的默认值
  * 在 application.properties 或 application.yml 文件中定义的值。
 9. 使用 @PropertySource 或 @PropertySources 加载的文件
  * 显式加载的配置文件,例如:

@PropertySource("classpath:custom.properties")


 10. 默认属性
  * 程序中通过代码设置的默认值,例如:

@Value("${server.port:8080}")
private int port;



总结的优先级列表

从高到低优先级:

 1. 命令行参数
 2. @TestPropertySource
 3. @SpringBootTest 的属性
 4. Java 系统属性
 5. 环境变量
 6. RandomValuePropertySource
 7. 外部应用配置文件(application.properties 或 application.yml)
 8. 默认配置文件中的默认值
 9. @PropertySource 显式加载的属性文件
 10. 编码中的默认值

优先级细节补充

  * 如果某些属性值需要优先于配置文件或默认值,可以通过命令行传递或环境变量进行覆盖。
  * 如果一个配置同时存在于多个优先级相同的文件中(如多个 application-{profile}.properties),加载顺序将影响最终结果。
  * 环境变量和属性文件中的属性名不区分大小写,环境变量会自动将 . 替换为 _,例如 SERVER_PORT 会映射为 server.port。

示例:结合优先级的用法

 1. 在 application.properties 中定义:

server.port=8080


 2. 添加环境变量:

export SERVER_PORT=8082


 3. 使用命令行参数运行程序:

java -Dserver.port=8083 -jar app.jar --server.port=8084



最终,server.port 的值为 8084,因为命令行参数的优先级最高。