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

Spring中如何用@Value动态获取属性?现有方案遇Bean解析异常

当前方案的问题

你当前的写法存在SpEL与占位符解析顺序的问题:Spring会优先解析${}格式的占位符,此时里面嵌套的#{authAppConfiguration.appName}还未被SpEL引擎解析为实际值,Spring会把#{authAppConfiguration.appName}.oauth.tokenUrl整个字符串当作配置键去查找,自然找不到对应配置,导致报错。

可行的实现方式

方式一:基于@ConfigurationProperties的动态前缀(推荐)

虽然你提到@ConfigurationProperties不支持SpEL,但实际上它的prefix属性支持SpEL表达式,只需确保提供前缀的Bean先初始化即可:

  1. 保留AuthAppConfiguration(确保它先被加载):
@Component
public record AuthAppConfiguration(
        @Value("${app.name}")
        String appName
) {
}
  1. 修改AuthConfigurationProperties,用SpEL指定动态前缀:
@Component
@Validated
@DependsOn("authAppConfiguration")
@ConfigurationProperties(prefix = "#{authAppConfiguration.appName}.oauth")
public record AuthConfigurationProperties(
        @NotEmpty
        String tokenUrl,
        String jwksUrl,
        @Valid
        OauthClient client,
        @Valid
        ValidationProperties validation
) {
}

@DependsOn用于强制Spring先初始化authAppConfiguration Bean,避免前缀解析时出现依赖未就绪的问题。

方式二:通过Environment手动绑定属性

注入Environment和AuthAppConfiguration,手动拼接配置键并绑定属性,灵活性更高:

@Component
@Validated
public record AuthConfigurationProperties(
        @NotEmpty
        String tokenUrl,
        String jwksUrl,
        @Valid
        OauthClient client,
        @Valid
        ValidationProperties validation
) {
    public AuthConfigurationProperties(AuthAppConfiguration authAppConfig, Environment env) {
        String prefix = authAppConfig.appName() + ".oauth";
        // 绑定基础属性
        this.tokenUrl = env.getRequiredProperty(prefix + ".tokenUrl");
        this.jwksUrl = env.getProperty(prefix + ".jwksUrl");
        // 绑定嵌套属性
        Binder binder = Binder.get(env);
        this.client = binder.bind(prefix + ".client", OauthClient.class).orElseThrow();
        this.validation = binder.bind(prefix + ".validation", ValidationProperties.class).orElseThrow();
    }
}

方式三:修正@Value的SpEL写法

如果坚持使用@Value,需要调整写法让SpEL优先执行,再通过Environment获取属性:

@Component
@Validated
public record AuthConfigurationProperties(
        @Value("#{environment.getProperty(authAppConfiguration.appName + '.oauth.tokenUrl')}")
        @NotEmpty
        String tokenUrl,
        @Value("#{environment.getProperty(authAppConfiguration.appName + '.oauth.jwksUrl')}")
        String jwksUrl,
        @Valid
        OauthClient client,
        @Valid
        ValidationProperties validation
) {
    // 嵌套属性client、validation需手动绑定,可参考方式二的Binder实现
}

这种写法的缺点是嵌套属性无法自动绑定,需要额外处理,不如方式一简洁。

内容的提问来源于stack exchange,提问作者Jesus Herrera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:22:42