Spring PropertyPlaceholderHelper详解

简介: 《读尽源码》
  • 类全路径: org.springframework.util.PropertyPlaceholderHelper

parseStringValue

  • org.springframework.util.PropertyPlaceholderHelper#parseStringValue 这个方法是主要方法
protected String parseStringValue(
      String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
   // 占位符所在位置
   int startIndex = value.indexOf(this.placeholderPrefix);
   if (startIndex == -1) {
      return value;
   }
   // 返回值
   StringBuilder result = new StringBuilder(value);
   while (startIndex != -1) {
      // 寻找结尾占位符
      int endIndex = findPlaceholderEndIndex(result, startIndex);
      if (endIndex != -1) {
         // 返回值切分留下中间内容
         String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
         String originalPlaceholder = placeholder;
         if (visitedPlaceholders == null) {
            visitedPlaceholders = new HashSet<>(4);
         }
         if (!visitedPlaceholders.add(originalPlaceholder)) {
            throw new IllegalArgumentException(
                  "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
         }
         // Recursive invocation, parsing placeholders contained in the placeholder key.
         // 递归获取占位符内容
         placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
         // Now obtain the value for the fully resolved key...
         // 解析占位符内容获得真正的属性值
         String propVal = placeholderResolver.resolvePlaceholder(placeholder);
         if (propVal == null && this.valueSeparator != null) {
            int separatorIndex = placeholder.indexOf(this.valueSeparator);
            if (separatorIndex != -1) {
               String actualPlaceholder = placeholder.substring(0, separatorIndex);
               String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
               propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
               if (propVal == null) {
                  propVal = defaultValue;
               }
            }
         }
         if (propVal != null) {
            // Recursive invocation, parsing placeholders contained in the
            // previously resolved placeholder value.
            propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
            result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
            if (logger.isTraceEnabled()) {
               logger.trace("Resolved placeholder '" + placeholder + "'");
            }
            startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
         }
         else if (this.ignoreUnresolvablePlaceholders) {
            // Proceed with unprocessed value.
            startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
         }
         else {
            throw new IllegalArgumentException("Could not resolve placeholder '" +
                  placeholder + "'" + " in value \"" + value + "\"");
         }
         visitedPlaceholders.remove(originalPlaceholder);
      }
      else {
         startIndex = -1;
      }
   }
   return result.toString();
}Copy to clipboardErrorCopied

在这里还需要关注一个接口

  • 占位符解析.
@FunctionalInterface
public interface PlaceholderResolver {
   /**
    * Resolve the supplied placeholder name to the replacement value.
    * @param placeholderName the name of the placeholder to resolve
    * @return the replacement value, or {@code null} if no replacement is to be made
    */
   @Nullable
   String resolvePlaceholder(String placeholderName);
}Copy to clipboardErrorCopied

占位符解析请查看: PlaceholderResolver

findPlaceholderEndIndex

  • 寻找结尾占位符索引
/**
 * 寻找结尾占位符索引
 */
private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
   int index = startIndex + this.placeholderPrefix.length();
   int withinNestedPlaceholder = 0;
   while (index < buf.length()) {
      if (StringUtils.substringMatch(buf, index, this.placeholderSuffix)) {
         if (withinNestedPlaceholder > 0) {
            withinNestedPlaceholder--;
            index = index + this.placeholderSuffix.length();
         }
         else {
            return index;
         }
      }
      else if (StringUtils.substringMatch(buf, index, this.simplePrefix)) {
         withinNestedPlaceholder++;
         index = index + this.simplePrefix.length();
      }
      else {
         index++;
      }
   }
   return -1;
}


相关文章
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
1607 0
|
NoSQL 算法 JavaScript
Redis 实现限流的三种方式
Redis 实现限流的三种方式
|
11月前
|
自然语言处理 算法 搜索推荐
《当NLP邂逅GIS:跨界融合的无限可能》
自然语言处理(NLP)与地理信息系统(GIS)的融合正开启全新应用大门,带来智能地理信息检索、地理知识图谱构建、灾害预警优化及智能导航等创新。通过NLP理解复杂语义并转化为GIS指令,降低了用户门槛,提升了效率。然而,数据异构性、语义理解复杂性、计算资源瓶颈及复合型人才短缺等问题仍待解决。尽管面临挑战,未来NLP与GIS的深度融合将为各行业带来更多变革与发展机遇。
233 12
|
12月前
|
人工智能 自然语言处理 JavaScript
微软开源课程!21节课程教你开发生成式 AI 应用所需了解的一切
微软推出的生成式 AI 入门课程,涵盖 21 节课程,帮助开发者快速掌握生成式 AI 应用开发,支持 Python 和 TypeScript 代码示例。
1042 15
|
监控 API
【zookeeper 第四篇章】监控 Watcher
ZooKeeper通过Watcher机制实现了数据的发布/订阅功能。多个订阅者可以监听同一主题对象,一旦该对象状态变化,如节点内容或子节点列表变动,ZooKeeper会实时通知所有订阅者。Watcher架构包括ZooKeeper服务端、客户端及其Watcher管理器。客户端向服务端注册Watcher并保存至本地管理器中;当状态变化时,服务端通知客户端,触发相关Watcher回调处理逻辑。
378 2
|
Java 区块链
使用Java实现区块链智能合约
使用Java实现区块链智能合约
|
Java Shell Maven
JAVA实现PGP/GPG加解密加验签
JAVA实现PGP/GPG加解密加验签
3124 0
|
Unix 编译器 Shell
CMake构建Makefile深度解析:从底层原理到复杂项目(一)
CMake构建Makefile深度解析:从底层原理到复杂项目
1775 0
|
SQL 缓存 关系型数据库
MySQL(三)SQL优化、Buffer pool、Change buffer
MySQL(三)SQL优化、Buffer pool、Change buffer
454 0
|
SQL 分布式计算 大数据
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复