springboot框架下,请使用@ConfigurationProperties替代@Value加载配置

一、背景

  • 程序启动时,详细报错见下:

10:40:31.965 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘redisDistributedLocker’: Unsatisfied dependency expressed through field ‘redissonClient’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘redissonConfig’: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder ‘spring.redis.password’ in value “${spring.redis.password}”

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘redissonConfig’: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder ‘spring.redis.password’ in value “${spring.redis.password}”

其他报错信息,我就不贴出来了,提示我们读取不到spring.redis.password。
源码见下:

@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Value("${spring.redis.password}")
    private String password;
}

二、排查过程

  • 1、@Value注解使用时,需要注意属性值为空的情况
    如果您尝试获取一个不存在的属性或属性值为空,则会抛出异常。
    而我们开发环境搭建的redis,恰好就是没有密码的。
    所以,我们的配置是:
spring:
  redis:
    host: 192.168.81.116
    port: 6379
    timeout: PT3S

预期的配置却是:

即使spring.redis.password为空,也需要把它配置一个空值。

spring:
  redis:
    host: 192.168.81.116
    port: 6379
    timeout: PT3S
    password: 

你也可以修改上面的Java源码,一个冒号就可以增强程序的健壮性。

// 注意末尾加一个冒号,意味着可以为空
    @Value("${spring.redis.password:}")
    private String password;
  • 2、使用@ConfigurationProperties替换@Value
@Configuration
@Data
@RefreshScope
@ConfigurationProperties(prefix = "spring.redis")
public class RedissonConfig {

    private String host;

    private String port;

    private String password;
}
  • 3、nacos读取配置的优先级低
    这里以user-service服务为例,以示说明spring boot程序读取nacos配置。对应的源码类是NacosPropertySourceBuilder.java。
    它会读取四个DataId,分别是:

    • application.yml
    • private-user-service.yml
    • user-service
    • user-service.yml

所以在启动的时候,不出意外,你的程序也会打印警告信息:

2023-07-28 10:35:13.202 WARN 17588 — [ main] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[user-service] & group[DEFAULT_GROUP]

不要被他误导了,以为没有读取到nacos配置。

  • 4、试图把spring.redis.password配置到Nacos上, 仍旧报错
    所以,你如果不想增加@Value的默认值,也不想使用@ConfigurationProperties,那么你就必须在resources/application.yml文件里配置,像下面这样:
    springboot框架下,请使用@ConfigurationProperties替代@Value加载配置_第1张图片

三、总结

在我们封装jar包,或者写配置类的时候,一定要考虑配置项的可能为空情况以及动态刷新。

所以我建议你使用注解@ConfigurationProperties,并且增加@RefreshScope支持动态刷新,特别是业务上的配置项,修改后不用重启服务,做到及时刷新。

你可能感兴趣的:(spring,boot,后端,java)