optimize:optimize config module code (#520)

pull/530/head
lingxiao,wu 2 years ago committed by GitHub
parent de6aa9ce3b
commit efa4873753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,3 +12,4 @@
- [Fix typo & Code optimization](https://github.com/Tencent/spring-cloud-tencent/pull/507) - [Fix typo & Code optimization](https://github.com/Tencent/spring-cloud-tencent/pull/507)
- [BugfixBeanFactoryUtils returns all beans including beans defined in ancestor bean factories](https://github.com/Tencent/spring-cloud-tencent/pull/515) - [BugfixBeanFactoryUtils returns all beans including beans defined in ancestor bean factories](https://github.com/Tencent/spring-cloud-tencent/pull/515)
- [fix:fix only config file metadata can be used in routing bug.](https://github.com/Tencent/spring-cloud-tencent/pull/518) - [fix:fix only config file metadata can be used in routing bug.](https://github.com/Tencent/spring-cloud-tencent/pull/518)
- [optimizeoptimize config module code](https://github.com/Tencent/spring-cloud-tencent/pull/520)

@ -27,6 +27,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered; import org.springframework.core.PriorityOrdered;
import org.springframework.lang.NonNull;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@ -37,9 +38,9 @@ import org.springframework.util.ReflectionUtils;
public abstract class PolarisProcessor implements BeanPostProcessor, PriorityOrdered { public abstract class PolarisProcessor implements BeanPostProcessor, PriorityOrdered {
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) public Object postProcessBeforeInitialization(Object bean, @NonNull String beanName)
throws BeansException { throws BeansException {
Class clazz = bean.getClass(); Class<?> clazz = bean.getClass();
for (Field field : findAllField(clazz)) { for (Field field : findAllField(clazz)) {
processField(bean, beanName, field); processField(bean, beanName, field);
} }
@ -50,7 +51,7 @@ public abstract class PolarisProcessor implements BeanPostProcessor, PriorityOrd
} }
@Override @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
return bean; return bean;
} }
@ -77,15 +78,15 @@ public abstract class PolarisProcessor implements BeanPostProcessor, PriorityOrd
return Ordered.LOWEST_PRECEDENCE; return Ordered.LOWEST_PRECEDENCE;
} }
private List<Field> findAllField(Class clazz) { private List<Field> findAllField(Class<?> clazz) {
final List<Field> res = new LinkedList<>(); final List<Field> res = new LinkedList<>();
ReflectionUtils.doWithFields(clazz, field -> res.add(field)); ReflectionUtils.doWithFields(clazz, res::add);
return res; return res;
} }
private List<Method> findAllMethod(Class clazz) { private List<Method> findAllMethod(Class<?> clazz) {
final List<Method> res = new LinkedList<>(); final List<Method> res = new LinkedList<>();
ReflectionUtils.doWithMethods(clazz, method -> res.add(method)); ReflectionUtils.doWithMethods(clazz, res::add);
return res; return res;
} }
} }

@ -87,7 +87,7 @@ public class SpringValueProcessor extends PolarisProcessor implements BeanFactor
} }
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) public Object postProcessBeforeInitialization(Object bean, @NonNull String beanName)
throws BeansException { throws BeansException {
if (polarisConfigProperties.isAutoRefresh()) { if (polarisConfigProperties.isAutoRefresh()) {
super.postProcessBeforeInitialization(bean, beanName); super.postProcessBeforeInitialization(bean, beanName);

@ -71,7 +71,7 @@ public class PlaceholderHelper {
if (beanFactory.getBeanExpressionResolver() == null) { if (beanFactory.getBeanExpressionResolver() == null) {
return value; return value;
} }
Scope scope = (beanDefinition != null ? beanFactory Scope scope = (beanDefinition != null && beanDefinition.getScope() != null ? beanFactory
.getRegisteredScope(beanDefinition.getScope()) : null); .getRegisteredScope(beanDefinition.getScope()) : null);
return beanFactory.getBeanExpressionResolver() return beanFactory.getBeanExpressionResolver()
.evaluate(value, new BeanExpressionContext(beanFactory, scope)); .evaluate(value, new BeanExpressionContext(beanFactory, scope));
@ -92,7 +92,7 @@ public class PlaceholderHelper {
public Set<String> extractPlaceholderKeys(String propertyString) { public Set<String> extractPlaceholderKeys(String propertyString) {
Set<String> placeholderKeys = Sets.newHashSet(); Set<String> placeholderKeys = Sets.newHashSet();
if (Strings.isNullOrEmpty(propertyString) || (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString))) { if (!isPlaceholder(propertyString)) {
return placeholderKeys; return placeholderKeys;
} }
@ -147,6 +147,11 @@ public class PlaceholderHelper {
return placeholderKeys; return placeholderKeys;
} }
private boolean isPlaceholder(String propertyString) {
return !Strings.isNullOrEmpty(propertyString) &&
(isNormalizedPlaceholder(propertyString) || isExpressionWithPlaceholder(propertyString));
}
private boolean isNormalizedPlaceholder(String propertyString) { private boolean isNormalizedPlaceholder(String propertyString) {
return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.contains(PLACEHOLDER_SUFFIX); return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.contains(PLACEHOLDER_SUFFIX);
} }

@ -86,7 +86,7 @@ public class SpringValue {
private void injectMethod(Object newVal) private void injectMethod(Object newVal)
throws InvocationTargetException, IllegalAccessException { throws InvocationTargetException, IllegalAccessException {
Object bean = beanRef.get(); Object bean = beanRef.get();
if (bean == null) { if (bean == null || methodParameter.getMethod() == null) {
return; return;
} }
methodParameter.getMethod().invoke(bean, newVal); methodParameter.getMethod().invoke(bean, newVal);
@ -131,7 +131,12 @@ public class SpringValue {
.format("key: %s, beanName: %s, field: %s.%s", key, beanName, bean.getClass() .format("key: %s, beanName: %s, field: %s.%s", key, beanName, bean.getClass()
.getName(), field.getName()); .getName(), field.getName());
} }
if (null != methodParameter.getMethod()) {
return String.format("key: %s, beanName: %s, method: %s.%s", key, beanName, bean.getClass().getName(), return String.format("key: %s, beanName: %s, method: %s.%s", key, beanName, bean.getClass().getName(),
methodParameter.getMethod().getName()); methodParameter.getMethod().getName());
} }
else {
return String.format("key: %s, beanName: %s", key, beanName);
}
}
} }

@ -0,0 +1,153 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.spring.annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import com.tencent.cloud.polaris.config.spring.property.SpringValue;
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
import com.tencent.polaris.api.utils.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* Test for {@link SpringValueProcessor}.
*
* @author lingxiao.wlx
*/
public class SpringValueProcessorTest {
@Test
public void springValueFiledProcessorTest() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisConfigBootstrapAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(ValueTest.class))
.withConfiguration(AutoConfigurations.of(PolarisConfigAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + "conditionalOnConfigReflectEnabledTest")
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues("spring.cloud.polaris.config.refresh-type=" + RefreshType.REFLECT)
.withPropertyValues("spring.cloud.polaris.config.enabled=true")
.withPropertyValues("timeout=10000");
contextRunner.run(context -> {
SpringValueRegistry springValueRegistry = context.getBean(SpringValueRegistry.class);
PolarisConfigAutoConfiguration polarisConfigAutoConfiguration = context.getBean(PolarisConfigAutoConfiguration.class);
BeanFactory beanFactory = polarisConfigAutoConfiguration.beanFactory;
Collection<SpringValue> timeout = springValueRegistry.get(beanFactory, "timeout");
Assert.assertFalse(CollectionUtils.isEmpty(timeout));
Optional<SpringValue> springValueOptional = timeout.stream().findAny();
Assert.assertTrue(springValueOptional.isPresent());
SpringValue springValue = springValueOptional.get();
Assert.assertEquals("${timeout:1000}", springValue.getPlaceholder());
Assert.assertTrue(springValue.isField());
Assert.assertTrue(Objects.nonNull(springValue.getField()));
Assert.assertEquals("timeout", springValue.getField().getName());
Assert.assertEquals(int.class, springValue.getTargetType());
ValueTest bean = context.getBean(ValueTest.class);
Assert.assertEquals(10000, bean.timeout);
});
}
@Test
public void springValueMethodProcessorTest() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PolarisConfigBootstrapAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(ValueTest.class))
.withConfiguration(AutoConfigurations.of(PolarisConfigAutoConfiguration.class))
.withPropertyValues("spring.application.name=" + "conditionalOnConfigReflectEnabledTest")
.withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081")
.withPropertyValues("spring.cloud.polaris.config.refresh-type=" + RefreshType.REFLECT)
.withPropertyValues("spring.cloud.polaris.config.enabled=true")
.withPropertyValues("name=test");
contextRunner.run(context -> {
SpringValueRegistry springValueRegistry = context.getBean(SpringValueRegistry.class);
PolarisConfigAutoConfiguration polarisConfigAutoConfiguration = context.getBean(PolarisConfigAutoConfiguration.class);
BeanFactory beanFactory = polarisConfigAutoConfiguration.beanFactory;
Collection<SpringValue> name = springValueRegistry.get(beanFactory, "name");
Assert.assertFalse(CollectionUtils.isEmpty(name));
Optional<SpringValue> springValueOptional = name.stream().findAny();
Assert.assertTrue(springValueOptional.isPresent());
SpringValue springValue = springValueOptional.get();
Method method = springValue.getMethodParameter().getMethod();
Assert.assertTrue(Objects.nonNull(method));
Assert.assertEquals("setName", method.getName());
Assert.assertEquals("${name:1000}", springValue.getPlaceholder());
Assert.assertFalse(springValue.isField());
Assert.assertEquals(String.class, springValue.getTargetType());
Assert.assertEquals("test", ValueTest.name);
});
}
@Configuration
@EnableAutoConfiguration
static class PolarisConfigAutoConfiguration {
@Autowired
private BeanFactory beanFactory;
public BeanFactory getBeanFactory() {
return beanFactory;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
@Component
private static class ValueTest {
@Value("${timeout:1000}")
private int timeout;
private static String name;
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Value("${name:1000}")
public void setName(String name) {
ValueTest.name = name;
}
}
}

@ -0,0 +1,67 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.spring.property;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
/**
* Test example.
*
* @author lingxiao.wlx
*/
public class Person implements BeanFactoryAware {
private String name;
private String age;
private BeanFactory beanFactory;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}

@ -0,0 +1,88 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.spring.property;
import java.util.Set;
import com.tencent.polaris.api.utils.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for {@link PlaceholderHelper}.
*
* @author lingxiao.wlx
*/
public class PlaceholderHelperTest {
private static final PlaceholderHelper PLACEHOLDER_HELPER = new PlaceholderHelper();
@Test
public void extractNormalPlaceholderKeysTest() {
final String placeholderCase = "${some.key}";
final String placeholderCase1 = "${some.key:${some.other.key:100}}";
final String placeholderCase2 = "${${some.key}}";
final String placeholderCase3 = "${${some.key:other.key}}";
final String placeholderCase4 = "${${some.key}:${another.key}}";
final String placeholderCase5 = "#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')}";
Set<String> placeholderKeys = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase);
Assert.assertEquals(1, placeholderKeys.size());
Assert.assertTrue(placeholderKeys.contains("some.key"));
Set<String> placeholderKeys1 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase1);
Assert.assertEquals(2, placeholderKeys1.size());
Assert.assertTrue(placeholderKeys1.contains("some.key"));
Assert.assertTrue(placeholderKeys1.contains("some.other.key"));
Set<String> placeholderKeys2 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase2);
Assert.assertEquals(1, placeholderKeys2.size());
Assert.assertTrue(placeholderKeys2.contains("some.key"));
Set<String> placeholderKeys3 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase3);
Assert.assertEquals(1, placeholderKeys3.size());
Assert.assertTrue(placeholderKeys3.contains("some.key"));
Set<String> placeholderKeys4 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase4);
Assert.assertEquals(2, placeholderKeys4.size());
Assert.assertTrue(placeholderKeys4.contains("some.key"));
Assert.assertTrue(placeholderKeys4.contains("another.key"));
Set<String> placeholderKeys5 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase5);
Assert.assertEquals(2, placeholderKeys5.size());
Assert.assertTrue(placeholderKeys5.contains("some.key"));
Assert.assertTrue(placeholderKeys5.contains("another.key"));
}
@Test
public void extractIllegalPlaceholderKeysTest() {
final String placeholderCase = "${some.key";
final String placeholderCase1 = "{some.key}";
final String placeholderCase2 = "some.key";
Set<String> placeholderKeys = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase);
Assert.assertTrue(CollectionUtils.isEmpty(placeholderKeys));
Set<String> placeholderKeys1 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase1);
Assert.assertTrue(CollectionUtils.isEmpty(placeholderKeys1));
Set<String> placeholderKeys2 = PLACEHOLDER_HELPER.extractPlaceholderKeys(placeholderCase2);
Assert.assertTrue(CollectionUtils.isEmpty(placeholderKeys2));
}
}

@ -0,0 +1,75 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.spring.property;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import com.tencent.polaris.api.utils.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Test for {@link SpringValueDefinitionProcessor}.
*
* @author lingxiao.wlx
*/
public class SpringValueDefinitionProcessorTest {
@Test
public void springValueDefinitionProcessorTest() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Person person = context.getBean(Person.class);
SpringValueRegistry springValueRegistry = context.getBean(SpringValueRegistry.class);
BeanFactory beanFactory = person.getBeanFactory();
Collection<SpringValue> name = springValueRegistry.get(beanFactory, "name");
Assert.assertFalse(CollectionUtils.isEmpty(name));
Optional<SpringValue> nameSpringValueOptional = name.stream().findAny();
Assert.assertTrue(nameSpringValueOptional.isPresent());
SpringValue nameSpringValue = nameSpringValueOptional.get();
Method method = nameSpringValue.getMethodParameter().getMethod();
Assert.assertTrue(Objects.nonNull(method));
Assert.assertEquals("setName", method.getName());
Assert.assertEquals("${name:test}", nameSpringValue.getPlaceholder());
Assert.assertFalse(nameSpringValue.isField());
Assert.assertEquals(String.class, nameSpringValue.getTargetType());
Collection<SpringValue> age = springValueRegistry.get(beanFactory, "age");
Assert.assertFalse(CollectionUtils.isEmpty(age));
Optional<SpringValue> ageSpringValueOptional = age.stream().findAny();
Assert.assertTrue(ageSpringValueOptional.isPresent());
SpringValue ageSpringValue = ageSpringValueOptional.get();
Method method1 = ageSpringValue.getMethodParameter().getMethod();
Assert.assertTrue(Objects.nonNull(method1));
Assert.assertEquals("setAge", method1.getName());
Assert.assertEquals("${age:10}", ageSpringValue.getPlaceholder());
Assert.assertFalse(ageSpringValue.isField());
Assert.assertEquals(String.class, ageSpringValue.getTargetType());
}
}

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:application-test.properties"/>
<!--Person-->
<bean class="com.tencent.cloud.polaris.config.spring.property.Person">
<property name="name" value="${name:test}"/>
<property name="age" value="${age:10}"/>
</bean>
<!--SpringValueDefinitionProcessor to process xml config placeholders -->
<bean class="com.tencent.cloud.polaris.config.spring.property.SpringValueDefinitionProcessor">
<constructor-arg index="0" ref="helper"/>
<constructor-arg index="1" ref="polarisConfigProperties"/>
</bean>
<!--Placeholder helper functions -->
<bean id="helper" class="com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper"/>
<!--PolarisConfigProperties -->
<bean id="polarisConfigProperties" class="com.tencent.cloud.polaris.config.config.PolarisConfigProperties">
<property name="autoRefresh" value="true"/>
</bean>
<!--springValueRegistry -->
<bean id="springValueRegistry" class="com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry"/>
<!--Spring value processor of method -->
<bean class="com.tencent.cloud.polaris.config.spring.annotation.SpringValueProcessor">
<constructor-arg index="0" ref="helper"/>
<constructor-arg index="1" ref="springValueRegistry"/>
<constructor-arg index="2" ref="polarisConfigProperties"/>
</bean>
</beans>
Loading…
Cancel
Save