You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring @Value注入无法读取properties属性,@ConfigurationProperties正常,求原因

Why does @Value fail to inject properties while @ConfigurationProperties works?

Let's break down why your @Value injection is failing even though @ConfigurationProperties works, and how to fix it.

The Problem Recap

You have this component using constructor injection with @Value:

@Component
public class FaultsConfiguration {
    private int interval;
    @Autowired
    public FaultsConfiguration(@Value("${faults.interval}") int interval) {
        this.interval = interval;
    }
}

With application.properties containing:

faults.interval=130

This throws a IllegalArgumentException: Could not resolve placeholder 'faults.interval', but switching to @ConfigurationProperties works fine:

@Service
@ConfigurationProperties(prefix="faults")
@Data
@NoArgsConstructor
public class FaultsConfiguration {
    private int interval;
}

Root Cause: Initialization Order & Injection Timing

The key difference lies in when Spring resolves the properties for each approach:

  1. Constructor injection with @Value: Spring needs to resolve the placeholder ${faults.interval} before creating the bean instance (since it's required for the constructor). If the property sources (like application.properties) haven't been fully loaded into the Spring Environment yet, or the placeholder resolver (PropertySourcesPlaceholderConfigurer) isn't initialized, this fails.
  2. @ConfigurationProperties: This uses Spring's Binder API, which resolves properties after the bean is instantiated (via setters, which Lombok's @Data generates). By this point, the Environment is fully populated with all property sources, so the value is available.

Other possible contributing factors:

  • If you have a custom PropertyPlaceholderConfigurer (the older Spring framework class) in your project, it might override Spring Boot's default PropertySourcesPlaceholderConfigurer, which doesn't support the modern property source hierarchy that includes application.properties.
  • Constructor injection with @Value is more sensitive to bean initialization order than field/setter injection.

Fixes to Get @Value Working

Here are a few ways to resolve the issue:

1. Switch to Field or Setter Injection with @Value

Move the @Value annotation to a field or setter method, so property resolution happens after bean instantiation:

@Component
public class FaultsConfiguration {
    @Value("${faults.interval}")
    private int interval;

    // No-arg constructor (required for Spring to instantiate the bean first)
    public FaultsConfiguration() {
    }
}

Or with setter injection:

@Component
public class FaultsConfiguration {
    private int interval;

    @Autowired
    public void setInterval(@Value("${faults.interval}") int interval) {
        this.interval = interval;
    }
}

2. Ensure PropertySourcesPlaceholderConfigurer is Properly Configured

If you must use constructor injection, make sure Spring's PropertySourcesPlaceholderConfigurer is initialized before your FaultsConfiguration bean. In Spring Boot, this is usually auto-configured, but if you have custom property configs, explicitly define it:

@Configuration
public class PropertyConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

The static modifier ensures this bean is created early in the initialization process.

3. Replace Old PropertyPlaceholderConfigurer with PropertySourcesPlaceholderConfigurer

If you have any custom beans using the legacy PropertyPlaceholderConfigurer, replace them with PropertySourcesPlaceholderConfigurer—this class is designed to work with Spring Boot's environment and property sources.

内容的提问来源于stack exchange,提问作者J Person

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:40:27