PropertyPlaceholderConfigurer类源码解析理解,使用工具类替换{}

工具类的使用

return StrFillTool.item("test1", test1).item("test2", test2).target("/{test1}/{test2}");
public final class StrFillTool {
    private static final String PLACE_HOLDER_PREFIX = "{";
    private static final String PLACE_HOLDER_SUFFIX = "}";
    private static final String VALUE_SEPARATOR = ":";
    private static final String SIMPLE_PREFIX = "{";

    public static Builder item(String name, Object value) {
        return new Builder(name, value);
    }

    public static final class Builder {
        private Map<String, Object> dataMap;

        public Builder(String name, Object value) {
            this.dataMap = new HashMap<>();
            this.dataMap.put(name, value);
        }

        public Builder item(String name, Object value) {
            this.dataMap.put(name, value);
            return this;
        }

        public String target(String targetStr) {
            return target(targetStr, false);
        }

        public String target(String targetStr, boolean ignoreNull) {
            return parseStringValue(targetStr, new PlaceholderResolver() {
                @Override
                public String resolvePlaceholder(String placeholderName) {
                    Object placeholderValue = dataMap.get(placeholderName);
                    return null == placeholderValue ? null : placeholderValue.toString();
                }
            }, new HashSet<String>(), ignoreNull);
        }

        private static String parseStringValue(String strVal, PlaceholderResolver placeholderResolver
                , Set<String> visitedPlaceholders, Boolean ignoreUnresolvablePlaceholders) {
            StringBuilder result = new StringBuilder(strVal);

            int startIndex = strVal.indexOf(PLACE_HOLDER_PREFIX);
            while (startIndex != -1) {
                int endIndex = findPlaceholderEndIndex(result, startIndex);
                if (endIndex != -1) {
                    String placeholder = result.substring(startIndex + PLACE_HOLDER_PREFIX.length(), endIndex);
                    String originalPlaceholder = placeholder;
                    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, ignoreUnresolvablePlaceholders);
                    // Now obtain the value for the fully resolved key...
                    String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                    if (propVal == null && VALUE_SEPARATOR != null) {
                        int separatorIndex = placeholder.indexOf(VALUE_SEPARATOR);
                        if (separatorIndex != -1) {
                            String actualPlaceholder = placeholder.substring(0, separatorIndex);
                            String defaultValue = placeholder.substring(separatorIndex + VALUE_SEPARATOR.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, ignoreUnresolvablePlaceholders);
                        result.replace(startIndex, endIndex + PLACE_HOLDER_SUFFIX.length(), propVal);
                        startIndex = result.indexOf(PLACE_HOLDER_PREFIX, startIndex + propVal.length());
                    }
                    else if (ignoreUnresolvablePlaceholders) {
                        // Proceed with unprocessed value.
                        startIndex = result.indexOf(PLACE_HOLDER_PREFIX, endIndex + PLACE_HOLDER_SUFFIX.length());
                    }
                    else {
                        throw new IllegalArgumentException("Could not resolve placeholder '" +
                                placeholder + "'" + " in string value \"" + strVal + "\"");
                    }
                    visitedPlaceholders.remove(originalPlaceholder);
                }
                else {
                    startIndex = -1;
                }
            }

            return result.toString();
        }

        private static int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
            int index = startIndex + PLACE_HOLDER_PREFIX.length();
            int withinNestedPlaceholder = 0;
            while (index < buf.length()) {
                if (StringUtils.substringMatch(buf, index, PLACE_HOLDER_SUFFIX)) {
                    if (withinNestedPlaceholder > 0) {
                        withinNestedPlaceholder--;
                        index = index + PLACE_HOLDER_SUFFIX.length();
                    }
                    else {
                        return index;
                    }
                }
                else if (StringUtils.substringMatch(buf, index, SIMPLE_PREFIX)) {
                    withinNestedPlaceholder++;
                    index = index + SIMPLE_PREFIX.length();
                }
                else {
                    index++;
                }
            }
            return -1;
        }
    }

    private interface PlaceholderResolver {
        String resolvePlaceholder(String placeholderName);
    }

    private StrFillTool() {}
}

PropertyResourceConfigurer.postProcessBeanFactory方法

/**
 * {@linkplain #mergeProperties Merge}, {@linkplain #convertProperties convert} and
 * {@linkplain #processProperties process} properties against the given bean factory.
 * @throws BeanInitializationException if any properties cannot be loaded
 */
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   try {
      //加载locations属性中配置的所有properties文件中的属性
      Properties mergedProps = mergeProperties();

      //prop做key,value转换
      convertProperties(mergedProps);

      //解析el表达式中的属性,获取值,并加载到bean属性中
      processProperties(beanFactory, mergedProps);
   }
   catch (IOException ex) {
      throw new BeanInitializationException("Could not load properties", ex);
   }
}

StringValueResolver接口是一个通配符解析接口,默认解析替换${}中的值。
我们再进到doProcessProperties方法中看一下。

protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
      StringValueResolver valueResolver) {
    //注册StringValueResolver解析器
   BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
    //从BeanFactory中获取注册的beanNames
   String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
   for (String curName : beanNames) {
      // Check that we're not parsing our own bean definition,
      // to avoid failing on unresolvable placeholders in properties file locations.
      if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
          //初始化bean实例(自己除外)
         BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
         try {
             //设置元数据
            visitor.visitBeanDefinition(bd);
         }
         catch (Exception ex) {
            throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
         }
      }
   }

   // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
   beanFactoryToProcess.resolveAliases(valueResolver);

   // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
   beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}

这段代码很好理解
1.注册StringValueResolver解析器
2.从BeanFactory中获取注册的beanNames
3.初始化bean实例(自己除外)
4.调用visitor.visitBeanDefinition(bd);方法设置元数据。

我们再继续跟到visitBeanDefinition(bd)中去。

/**
 * Traverse the given BeanDefinition object and the MutablePropertyValues
 * and ConstructorArgumentValues contained in them.
 * @param beanDefinition the BeanDefinition object to traverse
 * @see #resolveStringValue(String)
 */
public void visitBeanDefinition(BeanDefinition beanDefinition) {
   visitParentName(beanDefinition);
   visitBeanClassName(beanDefinition);
   visitFactoryBeanName(beanDefinition);
   visitFactoryMethodName(beanDefinition);
   visitScope(beanDefinition);
   visitPropertyValues(beanDefinition.getPropertyValues());
   ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
   visitIndexedArgumentValues(cas.getIndexedArgumentValues());
   visitGenericArgumentValues(cas.getGenericArgumentValues());
}

我们继续跟到visitPropertyValues(beanDefinition.getPropertyValues())方法里

/**
     * Resolve the given String value, for example parsing placeholders.
     * @param strVal the original String value
     * @return the resolved String value
     */
    protected String resolveStringValue(String strVal) {
        if (this.valueResolver == null) {
            throw new IllegalStateException("No StringValueResolver specified - pass a resolver " +
                    "object into the constructor or override the 'resolveStringValue' method");
        }
        String resolvedValue = this.valueResolver.resolveStringValue(strVal);
        // Return original String if not modified.
        return (strVal.equals(resolvedValue) ? strVal : resolvedValue);
    }

跟到StringValueResolver.resolveStringValue(String strVal)方法中

protected String parseStringValue(
            String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

        StringBuilder result = new StringBuilder(strVal);

        int startIndex = strVal.indexOf(this.placeholderPrefix);
        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.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...
                // 返回配置文件中对应属性的value值
                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 string value \"" + strVal + "\"");
                }
                visitedPlaceholders.remove(originalPlaceholder);
            }
            else {
                startIndex = -1;
            }
        }

        return result.toString();
    }

大致逻辑,递归调用解析出${}中的字符串
通过String propVal = placeholderResolver.resolvePlaceholder(placeholder);方法从prop对象中获取到配置文件中对应的value。

返回配置文件中的value值到BeanDefinition对象中的MutablePropertyValues对象中

protected void visitPropertyValues(MutablePropertyValues pvs) {
        PropertyValue[] pvArray = pvs.getPropertyValues();
        for (PropertyValue pv : pvArray) {
            Object newVal = resolveValue(pv.getValue());
            if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {
                pvs.add(pv.getName(), newVal);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值