Spring源码深度解析(郝佳)-学习-字符串值解析-parseStringValue

20 篇文章 1 订阅
18 篇文章 0 订阅

        在Spring中有一个这样的工具方法parseStringValue(),比如在xml中的EL表达式解析,资源加载,@Value注解内容解析,都用到了这样一个工具类方法,今天我们就来看看这个方法的实现。

parseStringValue()

我们先来写一个main方法测试一下

public class SpringTest1_2 {

    private static final Map<String, String> wellKnownSimplePrefixes = new HashMap<String, String>(4);

    static {
        wellKnownSimplePrefixes.put("}", "{");
        wellKnownSimplePrefixes.put("]", "[");
        wellKnownSimplePrefixes.put(")", "(");
    }

    public static String placeholderPrefix = "${";

    public static String placeholderSuffix = "}";

    public static  String simplePrefix = "{";

    public static String valueSeparator = ":";

    public static boolean ignoreUnresolvablePlaceholders  = false;


    public static void main(String[] args) {
        String text = "${user}";
       String a =  parseStringValue(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
            @Override
            public String resolvePlaceholder(String placeholderName) {
                if(placeholderName.equals("user")){
                    return "zhansan";
                }else if (placeholderName.equals("{user}")){
                    return "xxx";
                }else if(placeholderName.equals("zhansan")){
                    return "lisi";
                }else if(placeholderName.equals("person")){
                    return "${person1}";
                }else if (placeholderName.equals("person1")){
                    return "${person}";
                }else if(placeholderName.equals("lisi")){
                    return "wangwu";
                }
                return null;
            }
        },new HashSet());
        System.out.println(a);
    }

    // ${${user}}
    // ${user}
    public static String parseStringValue(String strVal, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver, Set visitedPlaceholders) {
        StringBuilder result = new StringBuilder(strVal);
        int startIndex = strVal.indexOf(placeholderPrefix);
        while (startIndex != -1) {
            // 查找和当前 前缀(${)相匹配 后缀(})的index,比如 ${${user}}
            int endIndex = findPlaceholderEndIndex(result, startIndex);
            if (endIndex != -1) {
                String placeholder = result.substring(startIndex + placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (!visitedPlaceholders.add(originalPlaceholder)) {
                    // ${${person}} 避免循环依赖
                    throw new IllegalArgumentException(
                            "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
                }
                // 递归调用,获取 ${} 内的内容,比如${${user}} ,第一次执行 parseStringValue 方法变成${user},再一次执行parseStringValue 方法,得到user
                placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
                // 由上面得到的值调用resolvePlaceholder方法得到具体的值 zhansan
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                if (propVal == null && valueSeparator != null) {
                    // 如果要执行下面的情况,如下配置 ${user1:wangwu} 先解析得到 user1:wangwu ,通过user1:wangwu 找不到对应的值
                    // 那么通过 : 分隔,得到array[0]=user1 ,array[1] 是wangwu ,再通过user1 去解析,如果解析不到,则使用Array[1]作为
                    // 默认值
                    int separatorIndex = placeholder.indexOf(valueSeparator);
                    if (separatorIndex != -1) {
                        String actualPlaceholder = placeholder.substring(0, separatorIndex);
                        String defaultValue = placeholder.substring(separatorIndex + valueSeparator.length());
                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                        if (propVal == null) {
                            propVal = defaultValue;
                        }
                    }
                }

                if (propVal != null) {
                    // 对于正常情况都会走到下面来 ${user}
                    propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
                    result.replace(startIndex, endIndex + placeholderSuffix.length(), propVal);
                    startIndex = result.indexOf(placeholderPrefix, startIndex + propVal.length());
                }
                else if (ignoreUnresolvablePlaceholders) {
                    startIndex = result.indexOf(placeholderPrefix, endIndex + placeholderSuffix.length());
                }
                else {
                    throw new IllegalArgumentException("Could not resolve placeholder '" +
                            placeholder + "'" + " in string value \"" + strVal + "\"");
                }
                visitedPlaceholders.remove(originalPlaceholder);
            }
            else {
                startIndex = -1;
            }
        }
        return result.toString();
    }

    public static int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
        int index = startIndex + placeholderPrefix.length();
        int withinNestedPlaceholder = 0;
        while (index < buf.length()) {
            if (StringUtils.substringMatch(buf, index, placeholderSuffix)) {
                if (withinNestedPlaceholder > 0) {
                    withinNestedPlaceholder--;
                    index = index + placeholderSuffix.length();
                }
                else {
                    return index;
                }
            }
            else if (StringUtils.substringMatch(buf, index, simplePrefix)) {
                withinNestedPlaceholder++;
                index = index + simplePrefix.length();
            }
            else {
                index++;
            }
        }
        return -1;
    }
}

private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
     return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
         @Override
         public String resolvePlaceholder(String placeholderName) {
             return getPropertyAsRawString(placeholderName);
         }
     });
 }


public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
	return parseStringValue(value, placeholderResolver, new HashSet());
}

 protected abstract String getPropertyAsRawString(String key); 

        Spring在外部调用了doResolvePlaceholders方法传入了要解析的字符串 text ,以及PropertyPlaceholderHelper,返回了PropertyPlaceholderHelper类的replacePlaceholders方法调用,replacePlaceholders方法调用过程中传入解析的字符串 text及PlaceholderResolver接口实现类,replacePlaceholders方法内部调用了parseStringValue方法,PlaceholderResolver接口实现类实现resolvePlaceholder方法,而resolvePlaceholder方法内部调用了抽象方法getPropertyAsRawString,他将调用子类的getPropertyAsRawString方法,因此在parseStringValue()方法内部回调resolvePlaceholder方法时,实际上是调用子类的getPropertyAsRawString()方法。Spring通过将简单功能巧妙组合,从而保证代码的灵活性,可扩展性。
        Spring 每次像剥洋葱一样,一层一层往里剥,直到最里层,就使用placeholderResolver的resolvePlaceholder方法解析相应的值,而内部根据外层传入进来的placeholderResolver不同,从而调用不同的resolvePlaceholder方法。整个过程正如颜色的叠加,最里层的红色+外层绿色=黄色 ,黄色+蓝色=白色。如${{红色}}} = 白色
,通过代码巧妙组合,既达到代码的公用,又保证了代码灵活。

本文github地址是
https://github.com/quyixiao/spring_tiny/blob/master/src/main/java/com/spring_1_100/test_1_10/test/SpringTest1_2.java

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值