com.ideaaedi.commonspring.parser.StringValueResolverHelper Maven / Gradle / Ivy
package com.ideaaedi.commonspring.parser;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PlaceholderConfigurerSupport;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* StringValueResolver工具类
*
* @author JustryDeng
* @since 2100.6.5
*/
public class StringValueResolverHelper {
private static final String KEY = "key_";
private final PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer;
private StringValueResolverHelper(PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer) {
this.propertySourcesPlaceholderConfigurer = propertySourcesPlaceholderConfigurer;
}
/**
* 初始化上下文
*
* @see StringValueResolverHelper#init(Map, ConfigurableConversionService, Config)
*/
public static StringValueResolverHelper init(@Nullable Map env) {
return init(env, null, null);
}
/**
* 初始化上下文
*
* @see StringValueResolverHelper#init(Map, ConfigurableConversionService, Config)
*/
public static StringValueResolverHelper init(@Nullable Map env, @Nullable Config config) {
return init(env, null, config);
}
/**
* 初始化上下文
*
* @see StringValueResolverHelper#init(Map, ConfigurableConversionService, Config)
*/
public static StringValueResolverHelper init(@Nullable Map env,
@Nullable ConfigurableConversionService conversionService) {
return init(env, conversionService, null);
}
/**
* 初始化上下文 & 设置类型转换器
*
* @param env 上下文信息,用于替换对应的占位符
* @param conversionService 类型转换器
* @param config 配置
*
* @return 当前实例
*/
public static StringValueResolverHelper init(@Nullable Map env,
@Nullable ConfigurableConversionService conversionService,
@Nullable Config config) {
Environment environment = new AbstractEnvironment() {
@Override
protected void customizePropertySources(@NonNull MutablePropertySources propertySources) {
if (env != null) {
propertySources.addLast(new MapPropertySource("JdEnvironment", env));
}
}
@Override
@NonNull
protected ConfigurablePropertyResolver createPropertyResolver(@NonNull MutablePropertySources propertySources) {
PropertySourcesPropertyResolver propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources);
if (conversionService != null) {
propertySourcesPropertyResolver.setConversionService(conversionService);
}
return propertySourcesPropertyResolver;
}
};
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer() {
@Override
protected void processProperties(@NonNull ConfigurableListableBeanFactory beanFactoryToProcess,
@NonNull ConfigurablePropertyResolver propertyResolver) throws BeansException {
// config
Config currConfig = config == null ? defaultConfig() : config;
super.setPlaceholderPrefix(currConfig.getPlaceholderPrefix());
super.setPlaceholderSuffix(currConfig.getPlaceholderSuffix());
super.setValueSeparator(currConfig.getValueSeparator());
super.setIgnoreUnresolvablePlaceholders(currConfig.isIgnoreUnresolvablePlaceholders());
super.setTrimValues(currConfig.isTrimValues());
// invoke super
super.processProperties(beanFactoryToProcess, propertyResolver);
}
};
propertySourcesPlaceholderConfigurer.setEnvironment(environment);
return new StringValueResolverHelper(propertySourcesPlaceholderConfigurer);
}
/**
* 获取默认配置
*
* @return 默认配置
*/
public static Config defaultConfig() {
return new Config();
}
/**
* 解析表达式
*
* @param expression 待解析的表达式. 格式形如:${xxx}
*
* @return 解析后的表达式
*/
@Nullable
public String parse(@Nullable String expression) {
if (StringUtils.isBlank(expression)) {
return expression;
}
JdDefaultListableBeanFactory beanFactory = new JdDefaultListableBeanFactory();
Map map = new HashMap<>(2);
map.put(KEY, expression);
beanFactory.init(map);
propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory);
return beanFactory.getAliasMap().get(KEY);
}
/**
* 解析表达式
*
* @param exprMap 待解析的表达式map(map的values即为表达式. 表达式格式形如:${xxx})
*
* @return 解析后的表达式map
*/
@NonNull
public LinkedHashMap parse(@Nullable LinkedHashMap exprMap) {
if (CollectionUtils.isEmpty(exprMap)) {
return new LinkedHashMap<>(1);
}
JdDefaultListableBeanFactory beanFactory = new JdDefaultListableBeanFactory();
Map tmpMap = new HashMap<>(16);
int idx = 0;
for (String value : exprMap.values()) {
tmpMap.put(KEY + idx, value);
idx++;
}
beanFactory.init(tmpMap);
propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory);
Map aliasMap = beanFactory.getAliasMap();
LinkedHashMap linkedHashMap = new LinkedHashMap<>(16);
String key;
for (int i = 0; idx > 0; idx--) {
key = KEY + i;
linkedHashMap.put(key, aliasMap.get(key));
i++;
}
return linkedHashMap;
}
/**
* 解析表达式
*
* @param exprList 待解析的表达式集合。 表达式格式形如:${xxx}
*
* @return 解析后的表达式list
*/
@NonNull
public List parse(@Nullable List exprList) {
if (CollectionUtils.isEmpty(exprList)) {
return new ArrayList<>(1);
}
JdDefaultListableBeanFactory beanFactory = new JdDefaultListableBeanFactory();
Map tmpMap = new HashMap<>(2);
int size = exprList.size();
for (int i = 0; i < size; i++) {
tmpMap.put(KEY + i, exprList.get(i));
}
beanFactory.init(tmpMap);
propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory);
Map aliasMap = beanFactory.getAliasMap();
List list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(aliasMap.get(KEY + i));
}
return list;
}
/**
* (non-javadoc)
*/
private static class JdDefaultListableBeanFactory extends DefaultListableBeanFactory {
private static final Field aliasMapField;
static {
try {
aliasMapField = SimpleAliasRegistry.class.getDeclaredField("aliasMap");
aliasMapField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
}
}
@Getter
private Map aliasMap;
void init(Map keyAndExpression) {
try {
//noinspection unchecked
aliasMap = (Map) aliasMapField.get(this);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
aliasMap.putAll(keyAndExpression);
}
}
/**
* 配置类
*
* @author JustryDeng
* @since 2100.6.7
*/
@Setter
@Getter
public static class Config {
private Config() {
}
/**
* @see PlaceholderConfigurerSupport#placeholderPrefix
*/
private String placeholderPrefix = PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX;
/**
* @see PlaceholderConfigurerSupport#placeholderSuffix
*/
private String placeholderSuffix = PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX;
/**
* @see PlaceholderConfigurerSupport#valueSeparator
*/
private String valueSeparator = PlaceholderConfigurerSupport.DEFAULT_VALUE_SEPARATOR;
/**
* 是否对解析后的整体结果进行trim(而不是对占位符对应的值trim)
* @see PlaceholderConfigurerSupport#trimValues
*/
private boolean trimValues = false;
/**
* @see PlaceholderConfigurerSupport#ignoreUnresolvablePlaceholders
*/
private boolean ignoreUnresolvablePlaceholders = false;
}
}