@value 不能注入 final 或 static 字段,仅支持非静态、非 final 的实例字段;类必须由 spring 管理,推荐构造函数注入或 @configurationproperties。

@Value 注入只读属性(如 final 字段)或静态字段时,Spring 无法完成赋值,会报错或值为 null。这不是配置或路径问题,而是 Spring 依赖注入机制本身的限制:它只能对非静态、非 final 的实例字段,在 Bean 初始化阶段进行设值。
避免 final 字段直接用 @Value
Spring 不支持向 final 字段注入值(编译期不可变),即使加了 @Value,运行时也会跳过该字段,保持默认值(如 null 或 0)。
- ❌ 错误写法:
@Value("${app.timeout}")<br>private final int timeout = 3000; - ✅ 正确做法:去掉
final,改用构造函数注入(推荐)private final int timeout;<br><br>public MyService(@Value("${app.timeout:3000}") int timeout) {<br> this.timeout = timeout;<br>}
禁止 static 字段使用 @Value
静态变量属于类级别,而 Spring 的依赖注入发生在对象实例化之后,因此 @Value 对 static 字段完全无效。
- ❌ 错误写法:
@Value("${api.base-url}")<br>private static String baseUrl; - ✅ 替代方案:
• 声明为普通实例字段 +@Value,再通过@PostConstruct赋给静态变量;
• 或改用ConfigurationProperties绑定到一个可实例化的配置类中,再全局访问。
确保容器管理且非手动 new
只读语义常被误用于“我只读这个配置”,但若类本身没被 Spring 管理(比如 new ConfigUtil()),那无论字段是否 final 或 static,@Value 都不会生效。
- 必须加
@Component/@Service等注解,或通过@Bean方法注册; - 所有使用处都应通过
@Autowired获取,而非new实例; - 测试时需用
@SpringBootTest,不能用普通单元测试直接 new。
优先用 @ConfigurationProperties 替代 @Value
对于结构化配置(如多个关联属性),@ConfigurationProperties 更安全、类型更明确,且天然支持构造器绑定和校验。
- 示例:
@ConfigurationProperties(prefix = "app")<br>@Component<br>public class AppProperties {<br> private final int timeout;<br> private final String baseUrl;<br><br> public AppProperties(@Value("${app.timeout:3000}") int timeout,<br> @Value("${app.base-url}") String baseUrl) {<br> this.timeout = timeout;<br> this.baseUrl = baseUrl;<br> }<br>}











