@ConfigurationProperties(prefix = "jwt") 是 Spring Boot 里超核心的注解,清楚它的作用、用法和核心价值。

一、核心作用:把配置文件的 jwt.* 绑定到 Java 类

简单说:它能自动把 application.yml/application.properties 里以 jwt 为前缀的配置项,赋值到标注了这个注解的类的字段上

举个例子:你的配置文件里写了:

jwt:
  secret: abcdefghijklmnopqrstuvwxyz123456
  expiration: 7200000
  clock-skew-seconds: 300

你的 JwtProperties 类里写了:

@Data
@Component
@ConfigurationProperties(prefix = "jwt") // 前缀指定为 jwt
public class JwtProperties {
    private String secret;          // 对应 jwt.secret
    private Long expiration;        // 对应 jwt.expiration
    private Long clockSkewSeconds;  // 对应 jwt.clock-skew-seconds(自动转驼峰)
}

✅ 效果:Spring 启动时,会自动把配置里的 jwt.secret 赋值给 JwtProperties.secretjwt.expiration 赋值给 JwtProperties.expiration,不用你手动写 getValue("jwt.secret") 这种代码!

二、关键特性(为什么不用手动读取配置?)

1. 自动格式转换
  • 配置里的 7200000(字符串)→ 自动转成 Long 类型赋值给 expiration
  • 配置里的 jwt.clock-skew-seconds(短横线命名)→ 自动匹配类里的 clockSkewSeconds(驼峰命名),不用手动对应。
2. 类型安全

如果配置里写了非数字(比如 expiration: abc),Spring 启动时会直接报错,而不是运行时才发现类型不对,提前规避 bug。

3. 批量绑定

一个注解就能绑定所有 jwt.* 配置,不用写一堆 @Value("${jwt.secret}") 注解(尤其是配置项多的时候,超省心)。

对比一下两种写法:

表格

@ConfigurationProperties(推荐) @Value(繁琐)
只需要一个注解,批量绑定 每个字段都要加 @Value
支持类型自动转换、校验 手动转换类型,容易出错
代码整洁,配置项多的时候更易维护 配置项多了代码乱糟糟

三、使用条件(缺一不可)

  1. 必须加 @Component(或 @Configuration:让 Spring 把这个类当成 Bean 管理,才能自动赋值;
  2. 前缀要匹配prefix = "jwt" 要和配置里的顶级节点 jwt 一致;
  3. 字段名要匹配:配置里的 clock-skew-seconds 对应类里的 clockSkewSeconds(短横线转驼峰是 Spring 的默认规则)。

四、和 @Value 的核心区别

特性 @ConfigurationProperties @Value
批量绑定 ✅ 支持(一个注解绑所有) ❌ 单个绑定
短横线转驼峰 ✅ 自动支持 ❌ 手动写 ${jwt.clock-skew-seconds}
类型转换 ✅ 自动(String→Long/Integer) ❌ 手动转换(比如 @Value("${jwt.expiration}") Long expiration
启动时校验 ✅ 配置错误启动失败 ❌ 运行时才报错
适合场景 多个配置项(比如 JWT、数据库) 单个配置项(比如 app.name

总结

  1. @ConfigurationProperties(prefix = "jwt") 的核心是自动绑定配置文件中 jwt.* 到 Java 类,替代繁琐的手动读取;
  2. @Value 更适合 “一组相关配置”(比如 JWT 的 secret / 过期时间 / 时钟偏移),类型安全、易维护;

@Value 注解做全方位拆解

一、@Value 核心定义

@Value 是 Spring 提供的核心注解,核心作用是:将单个配置项(来自配置文件 / 环境变量 / 命令行)绑定到 Java 类的字段上,支持直接值、占位符、SpEL 表达式,灵活度极高。

简单说:只要是 Spring 能识别的配置(不管是 application.yml、自定义 .properties,还是环境变量),都能用 @Value 精准 “拎出来” 赋值给字段。

二、基础用法(直接套用)

1. 绑定配置文件中的普通值

yaml

# application.yml 中的配置
app:
  name: 我的应用
  port: 8080
  debug: true
@Component // 必须交给Spring管理,@Value才会生效
public class AppConfig {
    // 绑定字符串
    @Value("${app.name}")
    private String appName;
    
    // 绑定数字(自动类型转换)
    @Value("${app.port}")
    private Integer appPort;
    
    // 绑定布尔值
    @Value("${app.debug}")
    private Boolean appDebug;

    // 初始化时打印验证
    @PostConstruct
    public void printConfig() {
        System.out.println("appName: " + appName); // 输出:我的应用
        System.out.println("appPort: " + appPort); // 输出:8080
        System.out.println("appDebug: " + appDebug); // 输出:true
    }
}
2. 加默认值(避坑核心)

如果配置项不存在,直接写 @Value("${app.version}") 会导致 Spring 启动失败,必须加默认值

// 语法:${配置项:默认值}
@Value("${app.version:1.0.0}") // 配置不存在时用 1.0.0
private String appVersion;

@Value("${app.timeout:3000}") // 默认值支持数字
private Integer appTimeout;

@Value("${app.enable:true}") // 默认值支持布尔
private Boolean appEnable;
3. 绑定环境变量 / 命令行参数

@Value 能读取环境变量、命令行参数(优先级高于配置文件):

# 1. 设置环境变量
export JWT_SECRET=abc123

# 2. 启动应用时传命令行参数
java -jar app.jar --app.name=命令行应用
@Component
public class EnvConfig {
    // 读取环境变量
    @Value("${JWT_SECRET:默认密钥}")
    private String jwtSecret;
    
    // 读取命令行参数(覆盖配置文件的 app.name)
    @Value("${app.name}")
    private String appName;

    @PostConstruct
    public void print() {
        System.out.println("jwtSecret: " + jwtSecret); // 输出:abc123
        System.out.println("appName: " + appName); // 输出:命令行应用
    }
}

三、高级用法(SpEL 表达式)

@Value 支持 Spring 表达式(SpEL),能做简单计算、取值、判断,语法:#{表达式}

@Component
public class SpELConfig {
    // 1. 直接赋值(无需配置文件)
    @Value("直接写的值")
    private String directValue; // 输出:直接写的值

    // 2. 数学计算
    @Value("#{10 * 60 * 1000}") // 10分钟(毫秒)
    private Long tenMinutes; // 输出:600000

    // 3. 拼接字符串
    @Value("#{'应用名称:' + '${app.name}'}")
    private String appNameDesc; // 输出:应用名称:我的应用

    // 4. 读取系统属性
    @Value("#{systemProperties['user.name']}")
    private String userName; // 输出:当前系统用户名

    // 5. 条件判断
    @Value("#{${app.debug} ? '调试模式' : '生产模式'}")
    private String runMode; // app.debug=true 时输出:调试模式
}

四、避坑指南

1. ❌ 忘记加 @Component(或 @Service/@Controller 等)

@Value 只有在 Spring 管理的 Bean 中才会生效,普通类中使用会赋值失败(字段为 null):

// 错误写法:普通类,@Value 无效
public class NormalClass {
    @Value("${app.name}")
    private String appName; // null
}

// 正确写法:交给 Spring 管理
@Component
public class SpringBeanClass {
    @Value("${app.name}")
    private String appName; // 正常赋值
}
2. ❌ 配置项不存在且无默认值
// 错误:app.xxx 不存在,启动时报错
@Value("${app.xxx}")
private String xxx;

// 正确:加默认值
@Value("${app.xxx:默认值}")
private String xxx;
3. ❌ 类型不匹配

配置项是字符串,但字段是数字 / 布尔,Spring 会自动转换,但转换失败会报错:

yaml

# 配置
app:
  port: abc # 非数字
// 错误:String → Integer 转换失败,启动报错
@Value("${app.port}")
private Integer appPort;

// 避免:加默认值(默认值类型要匹配)
@Value("${app.port:8080}")
private Integer appPort; // 用默认值 8080
4. ❌ 静态字段无法赋值

@Value 不能直接给静态字段赋值,需通过 setter 方法:

@Component
public class StaticConfig {
    // 错误:静态字段直接赋值,结果为 null
    @Value("${app.name}")
    private static String appName;

    // 正确:通过非静态 setter 赋值
    private static String staticAppName;
    
    @Value("${app.name}")
    public void setStaticAppName(String appName) {
        StaticConfig.staticAppName = appName;
    }
}

五、@Value vs @ConfigurationProperties(核心区别)

场景 @Value @ConfigurationProperties
配置数量 单个 / 少量配置项(如 app.name 一组相关配置(如 JWT、数据库配置)
灵活性 支持 SpEL 表达式、环境变量、命令行参数 仅支持配置文件绑定,不支持 SpEL
类型安全 运行时才报错(如类型转换失败) 启动时校验,提前暴露问题
代码整洁度 配置多时代码繁琐(每个字段都要加注解) 一个注解批量绑定,代码整洁
默认值 支持(${key:默认值} 需在字段上手动赋值(如 private Long expiration = 7200000L

六、最佳实践

  1. 零散配置:用 @Value + 默认值(如 app.nameserver.port);
  2. 敏感配置:用 @Value("${JWT_SECRET:默认值}")(读取环境变量,避免硬编码);
  3. 复杂逻辑:用 SpEL 表达式(如计算、拼接、条件判断);
  4. 一组配置:优先用 @ConfigurationProperties(如 JWT、Redis 配置);
  5. 必选配置@Value("${key}")(无默认值,强制要求配置,启动失败时快速定位问题)。

总结

  1. @Value 核心是单个配置项绑定,灵活度高,支持占位符、SpEL、环境变量;
  2. 避坑关键:加默认值、交给 Spring 管理、避免静态字段直接赋值;
  3. 少量配置用 @Value,一组配置用 @ConfigurationProperties
  4. 生产环境中,敏感配置(如密钥)优先通过 @Value 读取环境变量,而非硬编码。

 

@PropertySource 核心定义

@PropertySource 是 Spring 提供的注解,核心作用是:加载 application.yml/properties 之外的自定义配置文件(默认 Spring 只加载 resources 下的 application 系列配置)。

简单说:如果你的配置不在 application.yml 里,而是放在 custom.properties/custom.yml 里,就需要用这个注解告诉 Spring “去加载这个文件”。

一、基础用法

1. 加载单个 .properties 文件(最常用)
// 1. 新建自定义配置文件:resources/custom.properties
custom.key=hello
custom.value=123
custom.desc=自定义配置

// 2. 配置类中加载该文件
@Configuration
// value:配置文件路径(classpath 指 resources 目录)
// encoding:指定编码,避免中文乱码
@PropertySource(value = "classpath:custom.properties", encoding = "UTF-8")
public class CustomConfig {

    // 3. 用 @Value 绑定配置(@PropertySource 只加载文件,不绑定配置)
    @Value("${custom.key}")
    private String customKey;

    @Value("${custom.value:456}") // 加默认值,避免配置不存在时报错
    private Integer customValue;

    // 测试输出
    @PostConstruct
    public void printConfig() {
        System.out.println("custom.key: " + customKey); // 输出 hello
        System.out.println("custom.value: " + customValue); // 输出 123
    }
}
2. 加载多个配置文件(用 @PropertySources
@Configuration
@PropertySources({
    @PropertySource("classpath:custom1.properties"),
    @PropertySource("classpath:custom2.properties") // 可加载多个
})
public class MultiConfig {
    @Value("${custom1.key}")
    private String key1;

    @Value("${custom2.key}")
    private String key2;
}

三、避坑点(新手最容易踩)

1. ❌ 默认不支持 YAML 文件(.yml

@PropertySource 原生只认识 .properties,直接加载 .yml 会失败:

// 错误写法:直接加载 custom.yml 会读不到配置
@PropertySource("classpath:custom.yml")

✅ 解决:自定义 YAML 加载器(两步搞定)

// 步骤1:自定义 YAML 加载器(可复用)
public class YamlPropertySourceLoader implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        // 加载 YAML 文件为 Properties 对象
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(resource.getResource());
        Properties properties = factory.getObject();
        // 返回 PropertySource(用文件名作为名称)
        return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
    }
}

// 步骤2:使用自定义加载器加载 YAML
@Configuration
@PropertySource(
    value = "classpath:custom.yml",
    factory = YamlPropertySourceLoader.class, // 指定自定义加载器
    encoding = "UTF-8"
)
public class YamlConfig {
    @Value("${custom.key}")
    private String customKey;
}
2. ❌ 配置文件路径写错
  • 正确路径:classpath:custom.propertiesclasspath 指向 src/main/resources);
  • 错误路径:classpath:/custom.properties(多了斜杠)、custom.properties(少了 classpath:);
  • 如果文件在 resources/config 下:classpath:config/custom.properties
3. ❌ 配置项不存在时无默认值

如果 custom.key 不存在,@Value("${custom.key}") 会直接报错,建议加默认值:

// 正确写法:冒号后是默认值
@Value("${custom.key:默认值}")
private String customKey;

四、高级用法(结合 @ConfigurationProperties 批量绑定)

如果自定义配置文件里有一组相关配置(比如 pay.ali.app-idpay.ali.private-key),可以结合 @ConfigurationProperties 批量绑定,比 @Value 更整洁:

// 1. 自定义配置文件:resources/pay.properties
pay.ali.app-id=123456
pay.ali.private-key=abcdefg
pay.ali.timeout=3000

// 2. 配置类
@Configuration
@PropertySource("classpath:pay.properties")
public class PayConfig {
    // 3. 批量绑定 pay.ali 前缀的配置
    @Bean
    @ConfigurationProperties(prefix = "pay.ali")
    public AliPayProperties aliPayProperties() {
        return new AliPayProperties();
    }

    // 4. 配置类
    @Data
    public static class AliPayProperties {
        private String appId; // 对应 pay.ali.app-id(自动转驼峰)
        private String privateKey; // 对应 pay.ali.private-key
        private Integer timeout; // 对应 pay.ali.timeout
    }

    // 测试
    @PostConstruct
    public void printPayConfig() {
        System.out.println("appId: " + aliPayProperties().getAppId()); // 123456
    }
}

五、和 application.yml 的配合使用

@PropertySource 加载的配置,优先级低于 application.yml,但高于默认值:

yaml

# application.yml(优先级更高)
custom.key=application里的值

properties

# custom.properties
custom.key=custom里的值
@Value("${custom.key:默认值}")
private String customKey; // 最终值是 "application里的值"

六、核心总结

  1. 核心作用:加载 application 系列之外的自定义配置文件;
  2. 基础用法@PropertySource("classpath:xxx.properties") + @Value
  3. 避坑重点
    • 原生不支持 YAML,需自定义加载器;
    • 路径要写对(classpath: 开头);
    • @Value 加默认值避免空指针;
  4. 最佳实践
    • 零散配置:@PropertySource + @Value
    • 一组配置:@PropertySource + @ConfigurationProperties
    • 中文配置:一定要加 encoding = "UTF-8"
1. @PropertySource 注意事项
  • ❌ 默认不支持 YAML 文件(如 custom.yml),只能加载 .properties;若要加载 YAML,需引入依赖 + 自定义加载器:

    xml

    <!-- 引入依赖 -->
    <dependency>
        <groupId>org.yaml</groupId>
        <artifactId>snakeyaml</artifactId>
    </dependency>
    
    // 自定义 YAML 加载器
    public class YamlPropertySourceLoader extends PropertySourceFactory {
        @Override
        public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(resource.getResource());
            Properties properties = factory.getObject();
            return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
        }
    }
    // 使用
    @PropertySource(value = "classpath:custom.yml", factory = YamlPropertySourceLoader.class)
    
  • ✅ 支持指定编码(如 encoding = "UTF-8"),避免中文乱码。
2. 配置优先级(覆盖规则)

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

命令行参数 > 环境变量 > 自定义配置文件(@PropertySource)> application-{profile}.yml > application.yml

比如:命令行传 --jwt.secret=123 会覆盖 application.yml 里的 jwt.secret

3. @ConfigurationProperties 高级用法
  • 配置校验:配合 @Validated + JSR380 注解校验配置合法性:

    @Data
    @Component
    @Validated
    @ConfigurationProperties(prefix = "jwt")
    public class JwtProperties {
        @NotBlank(message = "jwt.secret 不能为空")
        private String secret;
        
        @Min(value = 3600000, message = "jwt.expiration 不能小于1小时")
        private Long expiration;
    }
    

    若配置不满足,Spring 启动时直接报错,提前规避问题。

  • 松散绑定:支持多种命名格式匹配:配置里的 jwt.clock-skew-seconds ↔ 类里的 clockSkewSeconds(驼峰)/ clock-skew-seconds(短横线)/ CLOCK_SKEW_SECONDS(大写下划线),无需严格一致。

三、最佳实践(新手直接套用)

场景 推荐方案
一组相关配置(如 JWT、数据库) @ConfigurationProperties + @Component(批量绑定 + 类型安全)
单个配置项(如 app.name @Value("${app.name:默认值}")(灵活 + 加默认值避免空指针)
加载自定义配置文件(如 custom.properties @PropertySource + @Value/@ConfigurationProperties
多环境配置(开发 / 测试 / 生产) application-dev.yml + application-prod.yml + spring.profiles.active
生产环境敏感配置(如 JWT 密钥) 环境变量 + ${JWT_SECRET:默认值}(避免硬编码)

@ConfigurationProperties@Value@PropertySource列表比对

一、核心配置读取方式汇总表

注解 / 方式 核心作用 语法示例 优点 缺点 适用场景
@ConfigurationProperties 批量绑定配置文件中同一前缀的配置项到 Java 类(类型安全) java<br>@Data<br>@Component<br>@ConfigurationProperties(prefix = "jwt")<br>public class JwtProperties {<br> private String secret;<br> private Long expiration;<br>} 1. 批量绑定,代码整洁2. 自动类型转换3. 短横线转驼峰4. 启动时校验配置 1. 只能绑定前缀下的配置2. 需配合 @Component 一组相关配置(如 JWT、数据库、Redis 配置)
@Value 单个绑定配置文件中的任意配置项(支持 SpEL 表达式) java<br>@Component<br>public class Test {<br> @Value("${jwt.secret}")<br> private String secret;<br> @Value("${jwt.expiration:7200000}") // 加默认值<br> private Long expiration;<br>} 1. 灵活,可绑定任意配置2. 支持默认值3. 支持 SpEL(如 @Value("#{10*60*1000}") 1. 单个绑定,配置多时代码繁琐2. 类型转换需手动保证3. 运行时才报错(非启动时) 单个 / 少量配置项(如 app.nameserver.port
@PropertySource 加载自定义路径 / 格式的配置文件(默认只加载 application.yml/properties) java<br>@Configuration<br>@PropertySource(value = "classpath:custom.properties", encoding = "UTF-8")<br>public class CustomConfig {<br> @Value("${custom.key}")<br> private String customKey;<br>} 1. 加载非默认配置文件(如 custom.properties)2. 支持指定编码 1. 只加载文件,不绑定配置2. 需配合 @Value/@ConfigurationProperties 使用3. 默认不支持 YAML(需额外依赖) 加载自定义配置文件(如业务配置、第三方配置)
@PropertySources 批量加载多个自定义配置文件(@PropertySource 的批量版) java<br>@Configuration<br>@PropertySources({<br> @PropertySource("classpath:custom1.properties"),<br> @PropertySource("classpath:custom2.properties")<br>})<br>public class MultiConfig {} 批量加载多个配置文件,语法更简洁 @PropertySource 的缺点 需加载多个自定义配置文件时

二、核心总结

  1. @ConfigurationProperties:批量绑定 “一组配置”,类型安全,启动时校验,适合框架 / 组件配置(如 JWT、数据库);
  2. @Value:灵活绑定 “单个配置”,支持 SpEL,适合零散配置;
  3. @PropertySource:加载 “自定义配置文件”,需配合前两者使用,默认只支持 .properties
  4. 优先级:命令行 > 环境变量 > 自定义配置 > 环境配置 > 默认配置;
  5. 生产环境:敏感配置(如密钥)用环境变量,避免硬编码在配置文件里。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐