From 9484b0b4df82ee83eb0c8a461c02df457e20bd37 Mon Sep 17 00:00:00 2001 From: yanhom Date: Sat, 8 Jul 2023 23:49:47 +0800 Subject: [PATCH] [ISSUE #307] support springboot 1.x property binding --- .../binder/SpringBootPropertiesBinder.java | 69 +++++++++++++++++-- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/starter/starter-common/src/main/java/org/dromara/dynamictp/starter/common/binder/SpringBootPropertiesBinder.java b/starter/starter-common/src/main/java/org/dromara/dynamictp/starter/common/binder/SpringBootPropertiesBinder.java index 17cca9454..067ac8365 100644 --- a/starter/starter-common/src/main/java/org/dromara/dynamictp/starter/common/binder/SpringBootPropertiesBinder.java +++ b/starter/starter-common/src/main/java/org/dromara/dynamictp/starter/common/binder/SpringBootPropertiesBinder.java @@ -17,16 +17,22 @@ package org.dromara.dynamictp.starter.common.binder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.dromara.dynamictp.common.properties.DtpProperties; import org.dromara.dynamictp.core.spring.PropertiesBinder; -import org.springframework.beans.BeanUtils; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValues; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; import org.springframework.core.ResolvableType; import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.Map; import static org.dromara.dynamictp.common.constant.DynamicTpConst.MAIN_PROPERTIES_PREFIX; @@ -37,24 +43,77 @@ * @author yanhom * @since 1.0.3 **/ +@Slf4j public class SpringBootPropertiesBinder implements PropertiesBinder { @Override public void bindDtpProperties(Map properties, DtpProperties dtpProperties) { + try { + Class.forName("org.springframework.boot.context.properties.bind.Binder"); + doBindIn2X(properties, dtpProperties); + } catch (Exception e) { + doBindIn1X(properties, dtpProperties); + } + } + + @Override + public void bindDtpProperties(Environment environment, DtpProperties dtpProperties) { + try { + Class.forName("org.springframework.boot.context.properties.bind.Binder"); + doBindIn2X(environment, dtpProperties); + } catch (Exception e) { + doBindIn1X(environment, dtpProperties); + } + } + + private void doBindIn2X(Map properties, DtpProperties dtpProperties) { ConfigurationPropertySource sources = new MapConfigurationPropertySource(properties); Binder binder = new Binder(sources); ResolvableType type = ResolvableType.forClass(DtpProperties.class); Bindable target = Bindable.of(type).withExistingValue(dtpProperties); binder.bind(MAIN_PROPERTIES_PREFIX, target); - BeanUtils.copyProperties(dtpProperties, DtpProperties.getInstance()); } - @Override - public void bindDtpProperties(Environment environment, DtpProperties dtpProperties) { + private void doBindIn2X(Environment environment, DtpProperties dtpProperties) { Binder binder = Binder.get(environment); ResolvableType type = ResolvableType.forClass(DtpProperties.class); Bindable target = Bindable.of(type).withExistingValue(dtpProperties); binder.bind(MAIN_PROPERTIES_PREFIX, target); - BeanUtils.copyProperties(dtpProperties, DtpProperties.getInstance()); + } + + @SuppressWarnings("all") + private void doBindIn1X(Environment environment, DtpProperties dtpProperties) { + try { + // new RelaxedPropertyResolver(environment) + Class resolverClass = Class.forName("org.springframework.boot.bind.RelaxedPropertyResolver"); + Constructor resolverConstructor = resolverClass.getDeclaredConstructor(PropertyResolver.class); + Object resolver = resolverConstructor.newInstance(environment); + + // resolver.getSubProperties(MAIN_PROPERTIES_PREFIX) + // return a map of all underlying properties that start with the specified key. + // NOTE: this method can only be used if the underlying resolver is a ConfigurableEnvironment. + Method getSubPropertiesMethod = resolverClass.getDeclaredMethod("getSubProperties", String.class); + Map properties = (Map) getSubPropertiesMethod.invoke(resolver, StringUtils.EMPTY); + + doBindIn1X(properties, dtpProperties); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("all") + private void doBindIn1X(Map properties, DtpProperties dtpProperties) { + try { + // new RelaxedDataBinder(dtpProperties, MAIN_PROPERTIES_PREFIX) + Class binderClass = Class.forName("org.springframework.boot.bind.RelaxedDataBinder"); + Constructor binderConstructor = binderClass.getDeclaredConstructor(Object.class, String.class); + Object binder = binderConstructor.newInstance(dtpProperties, MAIN_PROPERTIES_PREFIX); + + // binder.bind(new MutablePropertyValues(properties)) + Method bindMethod = binderClass.getMethod("bind", PropertyValues.class); + bindMethod.invoke(binder, new MutablePropertyValues(properties)); + } catch (Exception e) { + throw new RuntimeException(e); + } } }