Ändern Sie den Wert des Bean-Felds in der Map dynamisch
Schreiben Sie zunächst eine Klasse, um die BeanPostProcessor-Schnittstelle zu implementieren, und müssen Sie nur eine ihrer Funktionen verwenden. Es kann sowohl vorher als auch nachher implementiert werden und hat keinen Einfluss auf die endgültige Verwendung, da wir nur Instanzen von Beans benötigen.
package com.allen.apollo; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Configuration; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; import java.util.LinkedList; import java.util.List; import java.util.Set; @Configuration public class SpringValueProcessor implements BeanPostProcessor { private final PlaceholderHelper placeholderHelper = new PlaceholderHelper(); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("springValueController")) { Class obj = bean.getClass(); List<Field> fields = findAllField(obj); for (Field field : fields) { Value value = field.getAnnotation(Value.class); if (value != null) { Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value()); for (String key : keys) { SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false); SpringValueCacheMap.map.put(key, springValue); } } } } return bean; } private List<Field> findAllField(Class clazz) { final List<Field> res = new LinkedList<>(); ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { res.add(field); } }); return res; } }
Im obigen Code haben wir die Instanz-Bean von SpringValueController abgerufen und in der Karte gespeichert. Werfen wir einen Blick auf den Testcode
/** * cache field,存储bean 字段 */ package com.allen.apollo; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; public class SpringValueCacheMap { public static final Multimap<String, SpringValue> map = LinkedListMultimap.create(); }
package com.allen.apollo; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import org.springframework.core.MethodParameter; public class SpringValue { private MethodParameter methodParameter; private Field field; private WeakReference<Object> beanRef; private String beanName; private String key; private String placeholder; private Class<?> targetType; private Type genericType; private boolean isJson; public SpringValue(String key, String placeholder, Object bean, String beanName, Field field, boolean isJson) { this.beanRef = new WeakReference<>(bean); this.beanName = beanName; this.field = field; this.key = key; this.placeholder = placeholder; this.targetType = field.getType(); this.isJson = isJson; if (isJson) { this.genericType = field.getGenericType(); } } public SpringValue(String key, String placeholder, Object bean, String beanName, Method method, boolean isJson) { this.beanRef = new WeakReference<>(bean); this.beanName = beanName; this.methodParameter = new MethodParameter(method, 0); this.key = key; this.placeholder = placeholder; Class<?>[] paramTps = method.getParameterTypes(); this.targetType = paramTps[0]; this.isJson = isJson; if (isJson) { this.genericType = method.getGenericParameterTypes()[0]; } } public void update(Object newVal) throws IllegalAccessException, InvocationTargetException { if (isField()) { injectField(newVal); } else { injectMethod(newVal); } } private void injectField(Object newVal) throws IllegalAccessException { Object bean = beanRef.get(); if (bean == null) { return; } boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(bean, newVal); field.setAccessible(accessible); } private void injectMethod(Object newVal) throws InvocationTargetException, IllegalAccessException { Object bean = beanRef.get(); if (bean == null) { return; } methodParameter.getMethod().invoke(bean, newVal); } public String getBeanName() { return beanName; } public Class<?> getTargetType() { return targetType; } public String getPlaceholder() { return this.placeholder; } public MethodParameter getMethodParameter() { return methodParameter; } public boolean isField() { return this.field != null; } public Field getField() { return field; } public Type getGenericType() { return genericType; } public boolean isJson() { return isJson; } boolean isTargetBeanValid() { return beanRef.get() != null; } @Override public String toString() { Object bean = beanRef.get(); if (bean == null) { return ""; } if (isField()) { return String .format("key: %s, beanName: %s, field: %s.%s", key, beanName, bean.getClass().getName(), field.getName()); } return String.format("key: %s, beanName: %s, method: %s.%s", key, beanName, bean.getClass().getName(), methodParameter.getMethod().getName()); } }
package com.allen.apollo; import com.google.common.base.Strings; import com.google.common.collect.Sets; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.Scope; import org.springframework.util.StringUtils; import java.util.Set; import java.util.Stack; /** * Placeholder helper functions. */ public class PlaceholderHelper { private static final String PLACEHOLDER_PREFIX = "${"; private static final String PLACEHOLDER_SUFFIX = "}"; private static final String VALUE_SEPARATOR = ":"; private static final String SIMPLE_PLACEHOLDER_PREFIX = "{"; private static final String EXPRESSION_PREFIX = "#{"; private static final String EXPRESSION_SUFFIX = "}"; /** * Resolve placeholder property values, e.g. * <br /> * <br /> * "${somePropertyValue}" -> "the actual property value" */ public Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder) { // resolve string value String strVal = beanFactory.resolveEmbeddedValue(placeholder); BeanDefinition bd = (beanFactory.containsBean(beanName) ? beanFactory .getMergedBeanDefinition(beanName) : null); // resolve expressions like "#{systemProperties.myProp}" return evaluateBeanDefinitionString(beanFactory, strVal, bd); } private Object evaluateBeanDefinitionString(ConfigurableBeanFactory beanFactory, String value, BeanDefinition beanDefinition) { if (beanFactory.getBeanExpressionResolver() == null) { return value; } Scope scope = (beanDefinition != null ? beanFactory .getRegisteredScope(beanDefinition.getScope()) : null); return beanFactory.getBeanExpressionResolver() .evaluate(value, new BeanExpressionContext(beanFactory, scope)); } /** * Extract keys from placeholder, e.g. * <ul> * <li>${some.key} => "some.key"</li> * <li>${some.key:${some.other.key:100}} => "some.key", "some.other.key"</li> * <li>${${some.key}} => "some.key"</li> * <li>${${some.key:other.key}} => "some.key"</li> * <li>${${some.key}:${another.key}} => "some.key", "another.key"</li> * <li>#{new java.text.SimpleDateFormat("${some.key}").parse("${another.key}")} => "some.key", "another.key"</li> * </ul> */ public Set<String> extractPlaceholderKeys(String propertyString) { Set<String> placeholderKeys = Sets.newHashSet(); if (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString)) { return placeholderKeys; } Stack<String> stack = new Stack<>(); stack.push(propertyString); while (!stack.isEmpty()) { String strVal = stack.pop(); int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { placeholderKeys.add(strVal); continue; } int endIndex = findPlaceholderEndIndex(strVal, startIndex); if (endIndex == -1) { // invalid placeholder? continue; } String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); // ${some.key:other.key} if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) { stack.push(placeholderCandidate); } else { // some.key:${some.other.key:100} int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR); if (separatorIndex == -1) { stack.push(placeholderCandidate); } else { stack.push(placeholderCandidate.substring(0, separatorIndex)); String defaultValuePart = normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length())); if (!Strings.isNullOrEmpty(defaultValuePart)) { stack.push(defaultValuePart); } } } // has remaining part, e.g. ${a}.${b} if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) { String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length())); if (!Strings.isNullOrEmpty(remainingPart)) { stack.push(remainingPart); } } } return placeholderKeys; } private boolean isNormalizedPlaceholder(String propertyString) { return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.endsWith(PLACEHOLDER_SUFFIX); } private boolean isExpressionWithPlaceholder(String propertyString) { return propertyString.startsWith(EXPRESSION_PREFIX) && propertyString.endsWith(EXPRESSION_SUFFIX) && propertyString.contains(PLACEHOLDER_PREFIX); } private String normalizeToPlaceholder(String strVal) { int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { return null; } int endIndex = strVal.lastIndexOf(PLACEHOLDER_SUFFIX); if (endIndex == -1) { return null; } return strVal.substring(startIndex, endIndex + PLACEHOLDER_SUFFIX.length()); } private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { int index = startIndex + PLACEHOLDER_PREFIX.length(); int withinNestedPlaceholder = 0; while (index < buf.length()) { if (StringUtils.substringMatch(buf, index, PLACEHOLDER_SUFFIX)) { if (withinNestedPlaceholder > 0) { withinNestedPlaceholder--; index = index + PLACEHOLDER_SUFFIX.length(); } else { return index; } } else if (StringUtils.substringMatch(buf, index, SIMPLE_PLACEHOLDER_PREFIX)) { withinNestedPlaceholder++; index = index + SIMPLE_PLACEHOLDER_PREFIX.length(); } else { index++; } } return -1; } }rreee
Das obige ist der detaillierte Inhalt vonSo implementieren Sie SpringBoot2 Dynamic @Value. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!