diff --git a/changes/1.5.0.md b/changes/1.5.0.md index 42a2f97a08a..8f5b2bcaf72 100644 --- a/changes/1.5.0.md +++ b/changes/1.5.0.md @@ -101,6 +101,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 - [[#4408](https://github.com/seata/seata/pull/4408)] 修复容器环境中设置环境变量无效的问题 - [[#4441](https://github.com/seata/seata/pull/4441)] 修复redis模式下查询时未关闭Pipeline和分支注册后添加分支session时branchSessions为null的问题 - [[#4438](https://github.com/seata/seata/pull/4438)] 修复develop版本file模式下GlobalSession在延迟删除的情况下无法被正常删除的问题 + - [[#4432](https://github.com/seata/seata/pull/4432)] 修复develop版本下ServerApplicationListener无法读取配置中心配置的问题 ### optimize: diff --git a/changes/en-us/1.5.0.md b/changes/en-us/1.5.0.md index 47a6d28b5dd..9b81d0cabb4 100644 --- a/changes/en-us/1.5.0.md +++ b/changes/en-us/1.5.0.md @@ -103,6 +103,7 @@ - [[#4408](https://github.com/seata/seata/pull/4408)] fix the invalid environment variable in container env - [[#4441](https://github.com/seata/seata/pull/4441)] fix the problem that pipelined resources are not closed in redis mode and add branchSession judge branchSessions is not null - [[#4438](https://github.com/seata/seata/pull/4438)] fix the problem that GlobalSession could not be deleted normally in the case of delayed deletion in the file mode of the develop branch + - [[#4432](https://github.com/seata/seata/pull/4432)] fix the inability to get some remote configurations diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index 2591ba8f44c..a96d89b6c7f 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -109,6 +109,10 @@ public interface Constants { * The constant OBJECT_KEY_SPRING_APPLICATION_CONTEXT */ String OBJECT_KEY_SPRING_APPLICATION_CONTEXT = "springApplicationContext"; + /** + * The constant OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT + */ + String OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT = "springConfigurableEnvironment"; /** * The constant BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER */ diff --git a/common/src/main/java/io/seata/common/util/StringUtils.java b/common/src/main/java/io/seata/common/util/StringUtils.java index 123d0e0d9e5..9f48319ce1b 100644 --- a/common/src/main/java/io/seata/common/util/StringUtils.java +++ b/common/src/main/java/io/seata/common/util/StringUtils.java @@ -24,6 +24,8 @@ import java.util.Collection; import java.util.Date; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import io.seata.common.Constants; import io.seata.common.exception.ShouldNeverHappenException; @@ -36,6 +38,9 @@ */ public class StringUtils { + private static final Pattern CAMEL_PATTERN = Pattern.compile("[A-Z]"); + private static final Pattern LINE_PATTERN = Pattern.compile("-(\\w)"); + private StringUtils() { } @@ -319,4 +324,29 @@ public static boolean isEmpty(final CharSequence cs) { public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); } + + /** + * hump to Line or line to hump, only spring environment use + * + * @param str str + * @return string string + */ + public static String hump2Line(String str) { + Matcher matcher = CAMEL_PATTERN.matcher(str); + StringBuffer sb = new StringBuffer(); + if (matcher.find()) { + matcher.appendReplacement(sb, "-" + matcher.group(0).toLowerCase()); + while (matcher.find()) { + matcher.appendReplacement(sb, "-" + matcher.group(0).toLowerCase()); + } + } else { + matcher = LINE_PATTERN.matcher(str); + while (matcher.find()) { + matcher.appendReplacement(sb, matcher.group(1).toUpperCase()); + } + } + matcher.appendTail(sb); + return sb.toString(); + } + } diff --git a/common/src/test/java/io/seata/common/util/StringUtilsTest.java b/common/src/test/java/io/seata/common/util/StringUtilsTest.java index 6b853bfb891..36e31f79eb7 100644 --- a/common/src/test/java/io/seata/common/util/StringUtilsTest.java +++ b/common/src/test/java/io/seata/common/util/StringUtilsTest.java @@ -58,6 +58,13 @@ public void testIsNullOrEmpty() { assertThat(StringUtils.isNullOrEmpty(" ")).isFalse(); } + @Test + public void testHump2Line(){ + assertThat(StringUtils.hump2Line("abc-d").equals("abcD")).isTrue(); + assertThat(StringUtils.hump2Line("aBc").equals("a-bc")).isTrue(); + assertThat(StringUtils.hump2Line("abc").equals("abc")).isTrue(); + } + @Test public void testInputStream2String() throws IOException { assertNull(StringUtils.inputStream2String(null)); diff --git a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringApplicationContextProvider.java b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringApplicationContextProvider.java index b4374998f71..71390fb4fe8 100644 --- a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringApplicationContextProvider.java +++ b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringApplicationContextProvider.java @@ -23,15 +23,21 @@ import org.springframework.context.ApplicationContextAware; import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; /** * @author xingfudeshi@gmail.com + * @author funkye * The type spring application context provider */ public class SpringApplicationContextProvider implements ApplicationContextAware, BeanFactoryPostProcessor { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT, applicationContext); + if (ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT) == null) { + ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, + applicationContext.getEnvironment()); + } } @Override diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java index bf7d391aa57..5939248427a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/io/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java @@ -15,6 +15,7 @@ */ package io.seata.spring.boot.autoconfigure; +import io.seata.common.holder.ObjectHolder; import io.seata.rm.tcc.config.TCCFenceConfig; import io.seata.saga.engine.StateMachineConfig; import io.seata.spring.boot.autoconfigure.properties.SagaAsyncThreadPoolProperties; @@ -31,6 +32,7 @@ import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_RM_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.CLIENT_TM_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.COMPRESS_PREFIX; @@ -52,6 +54,7 @@ public class SeataClientEnvironmentPostProcessor implements EnvironmentPostProce @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, environment); PROPERTY_BEAN_MAP.put(SEATA_PREFIX, SeataProperties.class); PROPERTY_BEAN_MAP.put(CLIENT_RM_PREFIX, RmProperties.class); diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java index e63db906450..d81883b89b9 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java @@ -15,6 +15,7 @@ */ package io.seata.spring.boot.autoconfigure; +import java.util.concurrent.atomic.AtomicBoolean; import io.seata.spring.boot.autoconfigure.properties.LogProperties; import io.seata.spring.boot.autoconfigure.properties.ShutdownProperties; import io.seata.spring.boot.autoconfigure.properties.ThreadFactoryProperties; @@ -67,39 +68,49 @@ /** * @author xingfudeshi@gmail.com * @author wang.liang + * @author funkye */ public class SeataCoreEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + private static final AtomicBoolean INIT = new AtomicBoolean(false); + @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - PROPERTY_BEAN_MAP.put(CONFIG_PREFIX, ConfigProperties.class); - PROPERTY_BEAN_MAP.put(CONFIG_FILE_PREFIX, ConfigFileProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_PREFIX, RegistryProperties.class); - - PROPERTY_BEAN_MAP.put(CONFIG_NACOS_PREFIX, ConfigNacosProperties.class); - PROPERTY_BEAN_MAP.put(CONFIG_CONSUL_PREFIX, ConfigConsulProperties.class); - PROPERTY_BEAN_MAP.put(CONFIG_ZK_PREFIX, ConfigZooKeeperProperties.class); - PROPERTY_BEAN_MAP.put(CONFIG_APOLLO_PREFIX, ConfigApolloProperties.class); - PROPERTY_BEAN_MAP.put(CONFIG_ETCD3_PREFIX, ConfigEtcd3Properties.class); - PROPERTY_BEAN_MAP.put(CONFIG_CUSTOM_PREFIX, ConfigCustomProperties.class); - - PROPERTY_BEAN_MAP.put(REGISTRY_CONSUL_PREFIX, RegistryConsulProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_ETCD3_PREFIX, RegistryEtcd3Properties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_EUREKA_PREFIX, RegistryEurekaProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_NACOS_PREFIX, RegistryNacosProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_REDIS_PREFIX, RegistryRedisProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_SOFA_PREFIX, RegistrySofaProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_ZK_PREFIX, RegistryZooKeeperProperties.class); - PROPERTY_BEAN_MAP.put(REGISTRY_CUSTOM_PREFIX, RegistryCustomProperties.class); - - PROPERTY_BEAN_MAP.put(THREAD_FACTORY_PREFIX, ThreadFactoryProperties.class); - PROPERTY_BEAN_MAP.put(TRANSPORT_PREFIX, TransportProperties.class); - PROPERTY_BEAN_MAP.put(SHUTDOWN_PREFIX, ShutdownProperties.class); - PROPERTY_BEAN_MAP.put(LOG_PREFIX, LogProperties.class); + init(); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } + + public static void init() { + if (INIT.compareAndSet(false, true)) { + PROPERTY_BEAN_MAP.put(CONFIG_PREFIX, ConfigProperties.class); + PROPERTY_BEAN_MAP.put(CONFIG_FILE_PREFIX, ConfigFileProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_PREFIX, RegistryProperties.class); + + PROPERTY_BEAN_MAP.put(CONFIG_NACOS_PREFIX, ConfigNacosProperties.class); + PROPERTY_BEAN_MAP.put(CONFIG_CONSUL_PREFIX, ConfigConsulProperties.class); + PROPERTY_BEAN_MAP.put(CONFIG_ZK_PREFIX, ConfigZooKeeperProperties.class); + PROPERTY_BEAN_MAP.put(CONFIG_APOLLO_PREFIX, ConfigApolloProperties.class); + PROPERTY_BEAN_MAP.put(CONFIG_ETCD3_PREFIX, ConfigEtcd3Properties.class); + PROPERTY_BEAN_MAP.put(CONFIG_CUSTOM_PREFIX, ConfigCustomProperties.class); + + PROPERTY_BEAN_MAP.put(REGISTRY_CONSUL_PREFIX, RegistryConsulProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_ETCD3_PREFIX, RegistryEtcd3Properties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_EUREKA_PREFIX, RegistryEurekaProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_NACOS_PREFIX, RegistryNacosProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_REDIS_PREFIX, RegistryRedisProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_SOFA_PREFIX, RegistrySofaProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_ZK_PREFIX, RegistryZooKeeperProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_CUSTOM_PREFIX, RegistryCustomProperties.class); + + PROPERTY_BEAN_MAP.put(THREAD_FACTORY_PREFIX, ThreadFactoryProperties.class); + PROPERTY_BEAN_MAP.put(TRANSPORT_PREFIX, TransportProperties.class); + PROPERTY_BEAN_MAP.put(SHUTDOWN_PREFIX, ShutdownProperties.class); + PROPERTY_BEAN_MAP.put(LOG_PREFIX, LogProperties.class); + } + } + } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java index 6b6085916f6..1fa541f7d99 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/StarterConstants.java @@ -92,5 +92,6 @@ public interface StarterConstants { * The following special keys need to be normalized. */ String SPECIAL_KEY_GROUPLIST = "grouplist"; + String SPECIAL_KEY_SERVICE = "service"; String SPECIAL_KEY_VGROUP_MAPPING = "vgroupMapping"; } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index 35392358766..c552a6f0792 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -16,45 +16,51 @@ package io.seata.spring.boot.autoconfigure.provider; import java.lang.reflect.Field; -import java.lang.reflect.Method; +import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; - import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.holder.ObjectHolder; import io.seata.config.Configuration; import io.seata.config.ExtConfigurationProvider; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; -import org.springframework.cglib.proxy.MethodProxy; -import org.springframework.context.ApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; -import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; import static io.seata.common.util.StringFormatUtils.DOT; import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; import static io.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_GROUPLIST; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_SERVICE; import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_VGROUP_MAPPING; /** * @author xingfudeshi@gmail.com + * @author funkye */ public class SpringBootConfigurationProvider implements ExtConfigurationProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootConfigurationProvider.class); + private static final String INTERCEPT_METHOD_PREFIX = "get"; + private static final Map PROPERTY_BEAN_INSTANCE_MAP = new HashMap<>(64); + @Override public Configuration provide(Configuration originalConfiguration) { - return (Configuration) Enhancer.create(originalConfiguration.getClass(), new MethodInterceptor() { - @Override - public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) - throws Throwable { + return (Configuration)Enhancer.create(originalConfiguration.getClass(), + (MethodInterceptor)(proxy, method, args, methodProxy) -> { if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) { - Object result = null; - String rawDataId = (String) args[0]; + Object result; + String rawDataId = (String)args[0]; result = originalConfiguration.getConfigFromSys(rawDataId); if (null == result) { if (args.length == 1) { @@ -64,7 +70,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy } } if (result != null) { - //If the return type is String,need to convert the object to string + // If the return type is String,need to convert the object to string if (method.getReturnType().equals(String.class)) { return String.valueOf(result); } @@ -73,8 +79,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy } return method.invoke(originalConfiguration, args); - } - }); + }); } private Object get(String dataId, Object defaultValue) throws IllegalAccessException, InstantiationException { @@ -85,25 +90,29 @@ private Object get(String dataId, Object defaultValue) throws IllegalAccessExcep return result; } - private Object get(String dataId) throws IllegalAccessException, InstantiationException { + private Object get(String dataId) throws IllegalAccessException { String propertyPrefix = getPropertyPrefix(dataId); String propertySuffix = getPropertySuffix(dataId); - ApplicationContext applicationContext = (ApplicationContext) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT); Class propertyClass = PROPERTY_BEAN_MAP.get(propertyPrefix); Object valueObject = null; if (propertyClass != null) { try { - Object propertyBean = applicationContext.getBean(propertyClass); - valueObject = getFieldValue(propertyBean, propertySuffix, dataId); + valueObject = getFieldValue( + Objects.requireNonNull(PROPERTY_BEAN_INSTANCE_MAP.computeIfAbsent(propertyPrefix, k -> { + try { + return propertyClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + LOGGER.error("PropertyClass for prefix: [" + propertyPrefix + + "] should not be null. error :" + e.getMessage(), e); + } + return null; + })), propertySuffix, dataId); } catch (NoSuchBeanDefinitionException ignore) { } } else { throw new ShouldNeverHappenException("PropertyClass for prefix: [" + propertyPrefix + "] should not be null."); } - if (valueObject == null) { - valueObject = getFieldValue(propertyClass.newInstance(), propertySuffix, dataId); - } return valueObject; } @@ -118,19 +127,18 @@ private Object get(String dataId) throws IllegalAccessException, InstantiationEx * @author xingfudeshi@gmail.com */ private Object getFieldValue(Object object, String fieldName, String dataId) throws IllegalAccessException { - Object value = null; - Optional fieldOptional = Stream.of(object.getClass().getDeclaredFields()).filter( - f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); + Optional fieldOptional = Stream.of(object.getClass().getDeclaredFields()) + .filter(f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); if (fieldOptional.isPresent()) { Field field = fieldOptional.get(); - field.setAccessible(true); - value = field.get(object); - if (value instanceof Map) { - String key = StringUtils.substringAfterLast(dataId, String.valueOf(DOT)); - value = ((Map) value).get(key); + if (Objects.equals(field.getType(), Map.class)) { + return getConfig(dataId, null, String.class); } + field.setAccessible(true); + Object defaultValue = field.get(object); + return getConfig(dataId, defaultValue, field.getType()); } - return value; + return null; } /** @@ -141,8 +149,9 @@ private Object getFieldValue(Object object, String fieldName, String dataId) thr */ private String convertDataId(String rawDataId) { if (rawDataId.endsWith(SPECIAL_KEY_GROUPLIST)) { - String suffix = StringUtils.removeEnd(rawDataId, DOT + SPECIAL_KEY_GROUPLIST); - //change the format of default.grouplist to grouplist.default + String suffix = StringUtils.removeStart(StringUtils.removeEnd(rawDataId, DOT + SPECIAL_KEY_GROUPLIST), + SPECIAL_KEY_SERVICE + DOT); + // change the format of default.grouplist to grouplist.default return SERVICE_PREFIX + DOT + SPECIAL_KEY_GROUPLIST + DOT + suffix; } return SEATA_PREFIX + DOT + rawDataId; @@ -179,4 +188,22 @@ private String getPropertySuffix(String dataId) { } return StringUtils.substringAfterLast(dataId, String.valueOf(DOT)); } + + /** + * get spring config + * @param dataId data id + * @param defaultValue default value + * @param type type + * @return object + */ + private Object getConfig(String dataId, Object defaultValue, Class type) { + ConfigurableEnvironment environment = + (ConfigurableEnvironment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); + Object value = environment.getProperty(dataId, type); + if (value == null) { + value = environment.getProperty(io.seata.common.util.StringUtils.hump2Line(dataId), type); + } + return value != null ? value : defaultValue; + } + } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java index beb1a5cc857..7501da2ef67 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java @@ -20,8 +20,16 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext; import io.seata.common.holder.ObjectHolder; +import org.springframework.core.env.PropertiesPropertySource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; /** * @author slievrly @@ -39,7 +47,7 @@ public class BasePropertiesTest { protected static final long LONG_TEST_TWO = 2L; @BeforeEach - public void setUp() { + public void setUp() throws IOException { applicationContex = new AnnotationConfigApplicationContext( new String[] {"io.seata.spring.boot.autoconfigure.properties.config.test"}); SeataCoreEnvironmentPostProcessor processor = new SeataCoreEnvironmentPostProcessor(); @@ -47,6 +55,15 @@ public void setUp() { // set new applicationContex for test cases in extension test classes ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT, applicationContex); + ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, applicationContex.getEnvironment()); + Properties properties=new Properties(); + ClassLoader classLoader = getClass().getClassLoader(); + File f = new File(classLoader.getResource("application-test.properties").getFile()); + try(InputStream in =new FileInputStream(f)) { + properties.load(in); + } + applicationContex.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("serverProperties", properties)); + } @AfterEach diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties new file mode 100755 index 00000000000..eb1cadff1f2 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties @@ -0,0 +1,37 @@ + +seata.config.type=aaa +seata.config.data-type=bbb +seata.config.file.name=aaa + +seata.config.consul.server-addr=aaa +seata.config.consul.acl-token=bbb +seata.config.consul.key=ccc + +seata.config.apollo.apollo-access-key-secret=bbb +seata.config.apollo.apollo-meta=aaa +seata.config.apollo.app-id=ccc +seata.config.apollo.namespace=ddd +seata.config.apollo.cluster=eee +seata.config.apollo.apollo-config-service=fff + +seata.config.etcd3.server-addr=aaa +seata.config.etcd3.key=bbb + +seata.config.nacos.namespace=ddd +seata.config.nacos.server-addr=aaa +seata.config.nacos.group=ccc +seata.config.nacos.username=eee +seata.config.nacos.password=fff +##if use MSE Nacos with auth, mutex with username/password attribute +#seata.config.nacos.access-key= +#seata.config.nacos.secret-key= +seata.config.nacos.data-id=bbb + +seata.config.zk.server-addr=bbb +seata.config.zk.session-timeout=2 +seata.config.zk.connect-timeout=1 +seata.config.zk.username=ccc +seata.config.zk.password=ddd +seata.config.zk.node-path=aaa + +seata.config.custom.name=aaa diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java index e4857cb43dc..57f5d99a36c 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/io/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java @@ -15,6 +15,7 @@ */ package io.seata.spring.boot.autoconfigure; +import java.util.concurrent.atomic.AtomicBoolean; import io.seata.spring.boot.autoconfigure.properties.server.MetricsProperties; import io.seata.spring.boot.autoconfigure.properties.server.ServerProperties; import io.seata.spring.boot.autoconfigure.properties.server.ServerRecoveryProperties; @@ -50,25 +51,34 @@ */ public class SeataServerEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + private static final AtomicBoolean INIT = new AtomicBoolean(false); + @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - PROPERTY_BEAN_MAP.put(SERVER_PREFIX, ServerProperties.class); - PROPERTY_BEAN_MAP.put(SERVER_UNDO_PREFIX, ServerUndoProperties.class); - PROPERTY_BEAN_MAP.put(SERVER_RECOVERY_PREFIX, ServerRecoveryProperties.class); - PROPERTY_BEAN_MAP.put(METRICS_PREFIX, MetricsProperties.class); - PROPERTY_BEAN_MAP.put(STORE_PREFIX, StoreProperties.class); - PROPERTY_BEAN_MAP.put(STORE_SESSION_PREFIX, StoreProperties.Session.class); - PROPERTY_BEAN_MAP.put(STORE_LOCK_PREFIX, StoreProperties.Lock.class); - PROPERTY_BEAN_MAP.put(STORE_FILE_PREFIX, StoreFileProperties.class); - PROPERTY_BEAN_MAP.put(STORE_DB_PREFIX, StoreDBProperties.class); - PROPERTY_BEAN_MAP.put(STORE_REDIS_PREFIX, StoreRedisProperties.class); - PROPERTY_BEAN_MAP.put(STORE_REDIS_SINGLE_PREFIX, StoreRedisProperties.Single.class); - PROPERTY_BEAN_MAP.put(STORE_REDIS_SENTINEL_PREFIX, StoreRedisProperties.Sentinel.class); - PROPERTY_BEAN_MAP.put(SESSION_PREFIX, SessionProperties.class); + init(); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } + + public static void init() { + if (INIT.compareAndSet(false, true)) { + PROPERTY_BEAN_MAP.put(SERVER_PREFIX, ServerProperties.class); + PROPERTY_BEAN_MAP.put(SERVER_UNDO_PREFIX, ServerUndoProperties.class); + PROPERTY_BEAN_MAP.put(SERVER_RECOVERY_PREFIX, ServerRecoveryProperties.class); + PROPERTY_BEAN_MAP.put(METRICS_PREFIX, MetricsProperties.class); + PROPERTY_BEAN_MAP.put(STORE_PREFIX, StoreProperties.class); + PROPERTY_BEAN_MAP.put(STORE_SESSION_PREFIX, StoreProperties.Session.class); + PROPERTY_BEAN_MAP.put(STORE_LOCK_PREFIX, StoreProperties.Lock.class); + PROPERTY_BEAN_MAP.put(STORE_FILE_PREFIX, StoreFileProperties.class); + PROPERTY_BEAN_MAP.put(STORE_DB_PREFIX, StoreDBProperties.class); + PROPERTY_BEAN_MAP.put(STORE_REDIS_PREFIX, StoreRedisProperties.class); + PROPERTY_BEAN_MAP.put(STORE_REDIS_SINGLE_PREFIX, StoreRedisProperties.Single.class); + PROPERTY_BEAN_MAP.put(STORE_REDIS_SENTINEL_PREFIX, StoreRedisProperties.Sentinel.class); + PROPERTY_BEAN_MAP.put(SESSION_PREFIX, SessionProperties.class); + } + } + } diff --git a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java index 7b4761c9ed3..61f8baef129 100644 --- a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java +++ b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java @@ -49,6 +49,7 @@ public static void initContext() { @Bean RegistryRedisProperties registryRedisProperties() { RegistryRedisProperties registryRedisProperties = new RegistryRedisProperties().setPassword("123456").setDb(1).setServerAddr("localhost:123456"); + PROPERTY_BEAN_MAP.put(REGISTRY_REDIS_PREFIX, RegistryRedisProperties.class); return registryRedisProperties; } @@ -58,8 +59,11 @@ public void testReadConfigurationItems() { FileConfiguration configuration = mock(FileConfiguration.class); Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + System.setProperty("seata.registry.redis.db","1"); assertEquals(1, currentConfiguration.getInt("registry.redis.db")); + System.setProperty("seata.registry.redis.password","123456"); assertEquals("123456", currentConfiguration.getConfig("registry.redis.password")); + System.setProperty("seata.registry.redis.serverAddr","localhost:123456"); assertEquals("localhost:123456", currentConfiguration.getConfig("registry.redis.serverAddr")); } diff --git a/server/src/main/java/io/seata/server/ServerApplicationListener.java b/server/src/main/java/io/seata/server/ServerApplicationListener.java index 3819494b47e..f6c33c25cd0 100644 --- a/server/src/main/java/io/seata/server/ServerApplicationListener.java +++ b/server/src/main/java/io/seata/server/ServerApplicationListener.java @@ -16,8 +16,12 @@ package io.seata.server; import java.util.Properties; - +import io.seata.common.holder.ObjectHolder; import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.spring.boot.autoconfigure.SeataCoreEnvironmentPostProcessor; +import io.seata.spring.boot.autoconfigure.SeataServerEnvironmentPostProcessor; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.logging.LoggingApplicationListener; import org.springframework.context.ApplicationEvent; @@ -26,16 +30,18 @@ import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; +import static io.seata.common.ConfigurationKeys.STORE_LOCK_MODE; +import static io.seata.common.ConfigurationKeys.STORE_MODE; +import static io.seata.common.ConfigurationKeys.STORE_SESSION_MODE; +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; import static io.seata.common.DefaultValues.SERVICE_OFFSET_SPRING_BOOT; import static io.seata.core.constants.ConfigurationKeys.ENV_SEATA_PORT_KEY; import static io.seata.core.constants.ConfigurationKeys.SERVER_SERVICE_PORT_CAMEL; import static io.seata.core.constants.ConfigurationKeys.SERVER_SERVICE_PORT_CONFIG; -import static io.seata.core.constants.ConfigurationKeys.SERVER_STORE_SESSION_MODE; -import static io.seata.core.constants.ConfigurationKeys.SERVER_STORE_LOCK_MODE; -import static io.seata.core.constants.ConfigurationKeys.SERVER_STORE_MODE; /** * @author slievrly + * @author funkye */ public class ServerApplicationListener implements GenericApplicationListener { @@ -50,15 +56,17 @@ public void onApplicationEvent(ApplicationEvent event) { if (!(event instanceof ApplicationEnvironmentPreparedEvent)) { return; } - ApplicationEnvironmentPreparedEvent environmentPreparedEvent = (ApplicationEnvironmentPreparedEvent)event; ConfigurableEnvironment environment = environmentPreparedEvent.getEnvironment(); - + ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, environment); + SeataCoreEnvironmentPostProcessor.init(); + SeataServerEnvironmentPostProcessor.init(); + Configuration config = ConfigurationFactory.getInstance(); // Load by priority System.setProperty("sessionMode", - environment.getProperty(SERVER_STORE_SESSION_MODE, environmentPreparedEvent.getEnvironment().getProperty(SERVER_STORE_MODE, "file"))); + config.getConfig(STORE_SESSION_MODE, config.getConfig(STORE_MODE, "file"))); System.setProperty("lockMode", - environment.getProperty(SERVER_STORE_LOCK_MODE, environmentPreparedEvent.getEnvironment().getProperty(SERVER_STORE_MODE, "file"))); + config.getConfig(STORE_LOCK_MODE, config.getConfig(STORE_MODE, "file"))); String[] args = environmentPreparedEvent.getArgs(); @@ -75,7 +83,7 @@ public void onApplicationEvent(ApplicationEvent event) { } // -Dserver.servicePort=8091 - String dPort = environment.getProperty(SERVER_SERVICE_PORT_CAMEL); + String dPort = config.getConfig(SERVER_SERVICE_PORT_CAMEL); if (StringUtils.isNotBlank(dPort)) { setTargetPort(environment, dPort, true); return; @@ -88,8 +96,8 @@ public void onApplicationEvent(ApplicationEvent event) { return; } - //yml properties seata.server.service-port=8091 - String configPort = environment.getProperty(SERVER_SERVICE_PORT_CONFIG); + //yml properties server.servicePort=8091 + String configPort = config.getConfig(SERVER_SERVICE_PORT_CAMEL); if (StringUtils.isNotBlank(configPort)) { setTargetPort(environment, configPort, false); return;