Spring Boot中@Value注解始终使用默认值问题排查
核心原因
在Spring与Spring Boot混合配置(XML+Java Config)的场景下,传统XML配置中的PropertyPlaceholderConfigurer与Spring Boot默认的PropertySourcesPlaceholderConfigurer存在解析优先级冲突。前者是Spring传统的属性占位符处理器,后者是Spring Boot适配环境变量、配置文件的增强版处理器。当两者共存时,带默认值的@Value("${key:default}")表达式会被PropertyPlaceholderConfigurer优先处理——它无法识别Spring Boot的配置源(比如application.properties),直接返回默认值;而不带默认值的@Value("${key}")会因为前者找不到值抛出异常,触发Spring后续的PropertySourcesPlaceholderConfigurer处理,从而读取到配置文件中的值。
解决步骤
1. 移除XML中的PropertyPlaceholderConfigurer配置
如果XML里存在类似如下配置,直接删除:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:config.properties"/> </bean>
2. 统一用Java Config配置属性源
在你的Java配置类中,添加PropertySourcesPlaceholderConfigurer的Bean定义,确保它能加载所有需要的配置文件:
@Configuration public class PropertyConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); // 加载自定义配置文件,可添加多个 configurer.setLocations(new ClassPathResource("config.properties")); // 允许Spring Boot的默认配置源(application.properties/yaml)生效 configurer.setIgnoreUnresolvablePlaceholders(true); return configurer; } }
3. 确保配置类被扫描
保证你的Java配置类能被Spring Boot扫描到——可以在启动类添加@SpringBootApplication(默认扫描当前包及子包),或者用@ComponentScan指定配置类所在的包路径。
4. 测试验证
修改后重启应用,检查myPropertyWithDefault是否能正确读取配置文件中的值,而非默认值。
兼容XML的替代方案
如果必须保留XML配置,可在XML中改用PropertySourcesPlaceholderConfigurer替代PropertyPlaceholderConfigurer,并配置正确的参数:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:config.properties</value> </list> </property> <property name="ignoreUnresolvablePlaceholders" value="true"/> </bean>
内容的提问来源于stack exchange,提问作者Matthias M

