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

如何在Spring环境属性中自定义解析以something开头的占位符?

自定义Spring Boot属性占位符解析方案(针对something.*前缀)

刚好之前处理过类似的需求,给你分享一个优雅的实现方案——完全不用碰System.setProperty,而且能在Spring Property Resolver处理属性前,针对性解析所有以something.*开头的占位符。核心思路是通过自定义PropertySource包装原有属性源,并借助EnvironmentPostProcessor在Spring环境初始化阶段注入我们的逻辑,这样Spring解析属性时会优先经过我们的自定义处理。

实现步骤详解

1. 自定义PropertySource,拦截并处理目标属性

我们需要写一个PropertySource的实现类,把原有属性源包装起来,重写getProperty方法,对匹配something.*的键做自定义解析,其他属性则直接委托给原属性源处理。

import org.springframework.core.env.PropertySource;

public class CustomSomethingPropertySource extends PropertySource<Object> {
    private final PropertySource<?> delegate;

    // 构造方法传入要包装的原PropertySource
    public CustomSomethingPropertySource(PropertySource<?> delegate) {
        super("custom-something-" + delegate.getName(), delegate.getSource());
        this.delegate = delegate;
    }

    @Override
    public Object getProperty(String name) {
        // 匹配所有以something.开头的属性键
        if (name.startsWith("something.")) {
            // 这里替换成你的自定义解析逻辑
            // 示例:把something.xxx转换为custom_xxx的格式
            String keySuffix = name.substring("something.".length());
            return "custom_" + keySuffix;
            
            // 如果需要从外部数据源(比如数据库、配置中心)获取值,直接在这里调用对应的逻辑即可
        }
        // 非目标属性直接返回原属性源的结果
        return delegate.getProperty(name);
    }
}

2. 实现EnvironmentPostProcessor,注入自定义PropertySource

EnvironmentPostProcessor是Spring Boot提供的扩展点,允许我们在应用上下文创建前修改Environment。我们在这里把自定义的CustomSomethingPropertySource包装到原有属性源的前面,确保Spring解析属性时优先使用我们的逻辑。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.util.ArrayList;
import java.util.List;

public class CustomSomethingEnvironmentPostProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        MutablePropertySources propertySources = environment.getPropertySources();
        List<PropertySource<?>> targetSources = new ArrayList<>();

        // 收集需要包装的属性源(比如application.properties、application.yml对应的源)
        for (PropertySource<?> source : propertySources) {
            // 可以根据源的名称过滤,比如只处理应用配置相关的源
            if (source.getName().contains("applicationProperties") || source.getName().startsWith("applicationConfig:")) {
                targetSources.add(source);
            }
        }

        // 对每个目标源,包装成自定义PropertySource并添加到原位置的前面
        for (PropertySource<?> source : targetSources) {
            propertySources.addBefore(source.getName(), new CustomSomethingPropertySource(source));
        }
    }
}

3. 注册EnvironmentPostProcessor

在项目的src/main/resources/META-INF/目录下创建spring.factories文件,把我们的处理器注册进去,这样Spring Boot启动时会自动加载它:

org.springframework.boot.env.EnvironmentPostProcessor=com.yourpackage.CustomSomethingEnvironmentPostProcessor

(注意把com.yourpackage替换成你实际的包路径)

验证效果

比如在application.properties中添加:

# 目标占位符,会被自定义逻辑处理
demo.custom=${something.test-key}
# 普通属性,不受影响
demo.normal=original-value

然后在Spring组件中注入这两个属性:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class DemoComponent {
    @Value("${demo.custom}")
    private String customValue;

    @Value("${demo.normal}")
    private String normalValue;

    // 输出的话,customValue会是custom_test-key,normalValue是original-value
}

为什么不用System.setProperty?

这种方案完全避免了修改系统属性:

  • System.setProperty是全局的,会影响整个JVM内的所有应用,风险高;
  • 我们的实现只作用于当前Spring应用的Environment上下文,属性解析逻辑完全隔离,更安全可控。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:05:19