Property占位符处理:PropertySourcesPlaceholdersResolver

spring笔记-PropertyPlaceholderHelper
Spring源码解析之PropertyPlaceholderHelper(占位符解析器)

spring配置属性值中可以使用占位符,类似于MessageFormat中的占位符,例如 foo=我是${name},foo的最终值,是由key为name的value的值替换后的最终结果 ;
如果name 的值为 张三 ,那么 foo 就是"我是张三";如果name值是李四,那么foo就是 "我是李四";

Binder 中 的占位符解析器PropertySourcesPlaceholdersResolver,其内部是PropertyPlaceholderHelper
其构造函数中,指定了占位符的标识信息 开始和结束 分别是 ${} ;所以spring中的占位符用他们,当然这是个工具类,我们可以在单独在类似场景中使用;

new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,// "${"
                        SystemPropertyUtils.PLACEHOLDER_SUFFIX,// "}"
                        SystemPropertyUtils.VALUE_SEPARATOR,// ":"
                        true);

1.替换单个key
private final PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");

@Test
public void testWithProperties() {
    String text = "foo=${foo}";
    Properties props = new Properties();
    props.setProperty("foo", "bar");

    assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
}

2.替换多个key

    @Test
    public void testWithMultipleProperties() {
        String text = "foo=${foo},bar=${bar}";
        Properties props = new Properties();
        props.setProperty("foo", "bar");
        props.setProperty("bar", "baz");

        assertEquals("foo=bar,bar=baz", this.helper.replacePlaceholders(text, props));
    }

3.替换递归属性

    @Test
    public void testRecurseInProperty() {
        String text = "foo=${bar}";
        Properties props = new Properties();
        props.setProperty("bar", "${baz}");
        props.setProperty("baz", "bar");

        assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
    }

springboot的demo

@Autowired
    private ConfigurableEnvironment configurableEnvironment;

    /**
     * 配置文件中的内容
     * name=I'm [ ${name1} ]
     * name1=name1 say my name is [ ${name2} ]
     * name2=name2 say my name is [ ${name3} ]
     * name3=name3 say i have no name yet;
     */
    @Test
    void contextLoads() {
        Binder binder = Binder.get(configurableEnvironment);
        BindResult name = binder.bind("name", String.class);
        System.out.println(name.get());
        //I'm [ name1 say my name is [ name2 say my name is [ name3 say i have no name yet; ] ] ]
        //可嵌套
    }

spring内部的处理逻辑,把占位符中间的内容取出,作为key,在propertySouce中,取出value值,如果不是null,就替换,如果还有占位符,继续查找替换。

    @Override
    public Object resolvePlaceholders(Object value) {
        if (value != null && value instanceof String) {
            return this.helper.replacePlaceholders((String) value,
                    this::resolvePlaceholder);
        }
        return value;
    }

    protected String resolvePlaceholder(String placeholder) {
        if (this.sources != null) {
            for (PropertySource source : this.sources) {
                Object value = source.getProperty(placeholder);
                if (value != null) {
                    return String.valueOf(value);
                }
            }
        }
        return null;
    }

4.自定义占位符替换接口,
比如以下在replace时则不通过Properties数据源,而是通过自定义的数据源来处理

    @Test
    public void testWithResolver() {
        String text = "foo=${foo}";

        assertEquals("foo=bar",
                this.helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
                    @Override
                    public String resolvePlaceholder(String placeholderName) {
                        if ("foo".equals(placeholderName)) {
                            return "bar";
                        }
                        else {
                            return null;
                        }
                    }
                }));

你可能感兴趣的:(Property占位符处理:PropertySourcesPlaceholdersResolver)