parent
b5e06b906a
commit
f02428cd16
@ -1,41 +0,0 @@
|
|||||||
package com.tencent.cloud.polaris.config.config;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.tencent.cloud.polaris.config.listener.ConfigChangeListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*@author : wh
|
|
||||||
*@date : 2022/7/10 23:10
|
|
||||||
*@description:
|
|
||||||
*/
|
|
||||||
public class ConfigPropertySource extends EnumerablePropertySource<Config> {
|
|
||||||
private static final String[] EMPTY_ARRAY = new String[0];
|
|
||||||
|
|
||||||
ConfigPropertySource(String name, Config source) {
|
|
||||||
super(name, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsProperty(String name) {
|
|
||||||
return this.source.getProperty(name, null) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getPropertyNames() {
|
|
||||||
Set<String> propertyNames = this.source.getPropertyNames();
|
|
||||||
if (propertyNames.isEmpty()) {
|
|
||||||
return EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
return propertyNames.toArray(new String[propertyNames.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getProperty(String name) {
|
|
||||||
return this.source.getProperty(name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addChangeListener(ConfigChangeListener listener) {
|
|
||||||
this.source.addChangeListener(listener);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package com.tencent.cloud.polaris.config.config;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*@author : wh
|
|
||||||
*@date : 2022/7/10 23:10
|
|
||||||
*@description:
|
|
||||||
*/
|
|
||||||
public class ConfigPropertySourceFactory {
|
|
||||||
|
|
||||||
private final List<ConfigPropertySource> configPropertySources = Lists.newLinkedList();
|
|
||||||
|
|
||||||
public ConfigPropertySource getConfigPropertySource(String name, Config source) {
|
|
||||||
ConfigPropertySource configPropertySource = new ConfigPropertySource(name, source);
|
|
||||||
|
|
||||||
configPropertySources.add(configPropertySource);
|
|
||||||
|
|
||||||
return configPropertySource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ConfigPropertySource> getAllConfigPropertySources() {
|
|
||||||
return Lists.newLinkedList(configPropertySources);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
package com.tencent.cloud.polaris.config.config;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSortedSet;
|
|
||||||
import com.google.common.collect.LinkedHashMultimap;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.tencent.cloud.polaris.config.listener.ConfigChangeListener;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
|
||||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
|
||||||
import org.springframework.context.ApplicationEventPublisherAware;
|
|
||||||
import org.springframework.context.EnvironmentAware;
|
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.core.PriorityOrdered;
|
|
||||||
import org.springframework.core.env.CompositePropertySource;
|
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.core.env.MutablePropertySources;
|
|
||||||
import org.springframework.core.env.PropertySource;
|
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*@author : wh
|
|
||||||
*@date : 2022/7/10 23:09
|
|
||||||
*@description:
|
|
||||||
*/
|
|
||||||
public class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware,
|
|
||||||
ApplicationEventPublisherAware, PriorityOrdered {
|
|
||||||
private static final Multimap<Integer, String> NAMESPACE_NAMES = LinkedHashMultimap.create();
|
|
||||||
private static final Set<BeanFactory> AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES = Sets.newConcurrentHashSet();
|
|
||||||
|
|
||||||
private final ConfigPropertySourceFactory configPropertySourceFactory = SpringInjector
|
|
||||||
.getInstance(ConfigPropertySourceFactory.class);
|
|
||||||
private ConfigUtil configUtil;
|
|
||||||
private ConfigurableEnvironment environment;
|
|
||||||
private ApplicationEventPublisher applicationEventPublisher;
|
|
||||||
|
|
||||||
public static boolean addNamespaces(Collection<String> namespaces, int order) {
|
|
||||||
return NAMESPACE_NAMES.putAll(order, namespaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
this.configUtil = ApolloInjector.getInstance(ConfigUtil.class);
|
|
||||||
initializePropertySources();
|
|
||||||
initializeAutoUpdatePropertiesFeature(beanFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializePropertySources() {
|
|
||||||
if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME)) {
|
|
||||||
//already initialized
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CompositePropertySource composite;
|
|
||||||
if (configUtil.isPropertyNamesCacheEnabled()) {
|
|
||||||
composite = new CachedCompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME);
|
|
||||||
} else {
|
|
||||||
composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
//sort by order asc
|
|
||||||
ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());
|
|
||||||
Iterator<Integer> iterator = orders.iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
int order = iterator.next();
|
|
||||||
for (String namespace : NAMESPACE_NAMES.get(order)) {
|
|
||||||
Config config = ConfigService.getConfig(namespace);
|
|
||||||
|
|
||||||
composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NAMESPACE_NAMES.clear();
|
|
||||||
|
|
||||||
// add after the bootstrap property source or to the first
|
|
||||||
if (environment.getPropertySources()
|
|
||||||
.contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
|
|
||||||
|
|
||||||
if (configUtil.isOverrideSystemProperties()) {
|
|
||||||
// ensure ApolloBootstrapPropertySources is still the first
|
|
||||||
ensureBootstrapPropertyPrecedence(environment);
|
|
||||||
}
|
|
||||||
|
|
||||||
environment.getPropertySources()
|
|
||||||
.addAfter(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME, composite);
|
|
||||||
} else {
|
|
||||||
if (!configUtil.isOverrideSystemProperties()) {
|
|
||||||
if (environment.getPropertySources().contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
|
|
||||||
environment.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, composite);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
environment.getPropertySources().addFirst(composite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureBootstrapPropertyPrecedence(ConfigurableEnvironment environment) {
|
|
||||||
MutablePropertySources propertySources = environment.getPropertySources();
|
|
||||||
|
|
||||||
PropertySource<?> bootstrapPropertySource = propertySources
|
|
||||||
.get(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);
|
|
||||||
|
|
||||||
// not exists or already in the first place
|
|
||||||
if (bootstrapPropertySource == null || propertySources.precedenceOf(bootstrapPropertySource) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
propertySources.remove(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);
|
|
||||||
propertySources.addFirst(bootstrapPropertySource);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeAutoUpdatePropertiesFeature(ConfigurableListableBeanFactory beanFactory) {
|
|
||||||
if (!AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.add(beanFactory)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigChangeListener configChangeEventPublisher = changeEvent ->
|
|
||||||
applicationEventPublisher.publishEvent(new ApolloConfigChangeEvent(changeEvent));
|
|
||||||
|
|
||||||
List<ConfigPropertySource> configPropertySources = configPropertySourceFactory.getAllConfigPropertySources();
|
|
||||||
for (ConfigPropertySource configPropertySource : configPropertySources) {
|
|
||||||
configPropertySource.addChangeListener(configChangeEventPublisher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnvironment(Environment environment) {
|
|
||||||
//it is safe enough to cast as all known environment is derived from ConfigurableEnvironment
|
|
||||||
this.environment = (ConfigurableEnvironment) environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOrder() {
|
|
||||||
//make it as early as possible
|
|
||||||
return Ordered.HIGHEST_PRECEDENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test only
|
|
||||||
static void reset() {
|
|
||||||
NAMESPACE_NAMES.clear();
|
|
||||||
AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
|
||||||
this.applicationEventPublisher = applicationEventPublisher;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,223 +0,0 @@
|
|||||||
/*
|
|
||||||
package com.tencent.cloud.polaris.config.spring.annotation;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
|
|
||||||
import com.tencent.cloud.polaris.config.listener.ConfigChangeListener;
|
|
||||||
import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper;
|
|
||||||
import com.tencent.cloud.polaris.config.spring.property.SpringValue;
|
|
||||||
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
|
||||||
import org.springframework.context.EnvironmentAware;
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
*@author : wh
|
|
||||||
*@date : 2022/7/10 14:38
|
|
||||||
*@description:
|
|
||||||
*//*
|
|
||||||
|
|
||||||
public class PolarisAnnotationProcessor extends PolarisProcessor implements BeanFactoryAware,
|
|
||||||
EnvironmentAware {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PolarisAnnotationProcessor.class);
|
|
||||||
private static final Gson GSON = new Gson();
|
|
||||||
|
|
||||||
private final ConfigUtil configUtil;
|
|
||||||
private final PlaceholderHelper placeholderHelper;
|
|
||||||
private final SpringValueRegistry springValueRegistry;
|
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* resolve the expression.
|
|
||||||
*//*
|
|
||||||
|
|
||||||
private ConfigurableBeanFactory configurableBeanFactory;
|
|
||||||
|
|
||||||
private Environment environment;
|
|
||||||
|
|
||||||
public PolarisAnnotationProcessor(PlaceholderHelper placeholderHelper,
|
|
||||||
SpringValueRegistry springValueRegistry) {
|
|
||||||
|
|
||||||
configUtil = ApolloInjector.getInstance(ConfigUtil.class);
|
|
||||||
this.placeholderHelper = placeholderHelper;
|
|
||||||
this.springValueRegistry = springValueRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void processField(Object bean, String beanName, Field field) {
|
|
||||||
this.processApolloConfig(bean, field);
|
|
||||||
this.processApolloJsonValue(bean, beanName, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void processMethod(final Object bean, String beanName, final Method method) {
|
|
||||||
this.processApolloConfigChangeListener(bean, method);
|
|
||||||
this.processApolloJsonValue(bean, beanName, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processApolloConfig(Object bean, Field field) {
|
|
||||||
ApolloConfig annotation = AnnotationUtils.getAnnotation(field, ApolloConfig.class);
|
|
||||||
if (annotation == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()),
|
|
||||||
"Invalid type: %s for field: %s, should be Config", field.getType(), field);
|
|
||||||
|
|
||||||
final String namespace = annotation.value();
|
|
||||||
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
|
|
||||||
Config config = ConfigService.getConfig(resolvedNamespace);
|
|
||||||
|
|
||||||
ReflectionUtils.makeAccessible(field);
|
|
||||||
ReflectionUtils.setField(field, bean, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processApolloConfigChangeListener(final Object bean, final Method method) {
|
|
||||||
ApolloConfigChangeListener annotation = AnnotationUtils
|
|
||||||
.findAnnotation(method, ApolloConfigChangeListener.class);
|
|
||||||
if (annotation == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
|
||||||
Preconditions.checkArgument(parameterTypes.length == 1,
|
|
||||||
"Invalid number of parameters: %s for method: %s, should be 1", parameterTypes.length,
|
|
||||||
method);
|
|
||||||
Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]),
|
|
||||||
"Invalid parameter type: %s for method: %s, should be ConfigChangeEvent", parameterTypes[0],
|
|
||||||
method);
|
|
||||||
|
|
||||||
ReflectionUtils.makeAccessible(method);
|
|
||||||
String[] namespaces = annotation.value();
|
|
||||||
String[] annotatedInterestedKeys = annotation.interestedKeys();
|
|
||||||
String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
|
|
||||||
ConfigChangeListener configChangeListener = new ConfigChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onChange(ConfigChangeEvent changeEvent) {
|
|
||||||
ReflectionUtils.invokeMethod(method, bean, changeEvent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Set<String> interestedKeys =
|
|
||||||
annotatedInterestedKeys.length > 0 ? Sets.newHashSet(annotatedInterestedKeys) : null;
|
|
||||||
Set<String> interestedKeyPrefixes =
|
|
||||||
annotatedInterestedKeyPrefixes.length > 0 ? Sets.newHashSet(annotatedInterestedKeyPrefixes)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
for (String namespace : namespaces) {
|
|
||||||
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
|
|
||||||
Config config = ConfigService.getConfig(resolvedNamespace);
|
|
||||||
|
|
||||||
if (interestedKeys == null && interestedKeyPrefixes == null) {
|
|
||||||
config.addChangeListener(configChangeListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
config.addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void processApolloJsonValue(Object bean, String beanName, Field field) {
|
|
||||||
ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(field, ApolloJsonValue.class);
|
|
||||||
if (apolloJsonValue == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String placeholder = apolloJsonValue.value();
|
|
||||||
Object propertyValue = placeholderHelper
|
|
||||||
.resolvePropertyValue(this.configurableBeanFactory, beanName, placeholder);
|
|
||||||
|
|
||||||
// propertyValue will never be null, as @ApolloJsonValue will not allow that
|
|
||||||
if (!(propertyValue instanceof String)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean accessible = field.isAccessible();
|
|
||||||
field.setAccessible(true);
|
|
||||||
ReflectionUtils
|
|
||||||
.setField(field, bean, parseJsonValue((String) propertyValue, field.getGenericType()));
|
|
||||||
field.setAccessible(accessible);
|
|
||||||
|
|
||||||
if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
|
|
||||||
Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeholder);
|
|
||||||
for (String key : keys) {
|
|
||||||
SpringValue springValue = new SpringValue(key, placeholder, bean, beanName, field, true);
|
|
||||||
springValueRegistry.register(this.configurableBeanFactory, key, springValue);
|
|
||||||
logger.debug("Monitoring {}", springValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processApolloJsonValue(Object bean, String beanName, Method method) {
|
|
||||||
ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(method, ApolloJsonValue.class);
|
|
||||||
if (apolloJsonValue == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String placeHolder = apolloJsonValue.value();
|
|
||||||
|
|
||||||
Object propertyValue = placeholderHelper
|
|
||||||
.resolvePropertyValue(this.configurableBeanFactory, beanName, placeHolder);
|
|
||||||
|
|
||||||
// propertyValue will never be null, as @ApolloJsonValue will not allow that
|
|
||||||
if (!(propertyValue instanceof String)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type[] types = method.getGenericParameterTypes();
|
|
||||||
Preconditions.checkArgument(types.length == 1,
|
|
||||||
"Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters",
|
|
||||||
bean.getClass().getName(), method.getName(), method.getParameterTypes().length);
|
|
||||||
|
|
||||||
boolean accessible = method.isAccessible();
|
|
||||||
method.setAccessible(true);
|
|
||||||
ReflectionUtils.invokeMethod(method, bean, parseJsonValue((String) propertyValue, types[0]));
|
|
||||||
method.setAccessible(accessible);
|
|
||||||
|
|
||||||
if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
|
|
||||||
Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeHolder);
|
|
||||||
for (String key : keys) {
|
|
||||||
SpringValue springValue = new SpringValue(key, apolloJsonValue.value(), bean, beanName,
|
|
||||||
method, true);
|
|
||||||
springValueRegistry.register(this.configurableBeanFactory, key, springValue);
|
|
||||||
logger.debug("Monitoring {}", springValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object parseJsonValue(String json, Type targetType) {
|
|
||||||
try {
|
|
||||||
return GSON.fromJson(json, targetType);
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
logger.error("Parsing json '{}' to type {} failed!", json, targetType, ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
|
||||||
this.configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnvironment(Environment environment) {
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
package com.tencent.cloud.polaris.config.spring.annotation;
|
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
*@author : wh
|
|
||||||
*@date : 2022/7/10 14:38
|
|
||||||
*@description:
|
|
||||||
*//*
|
|
||||||
|
|
||||||
public class PolarisConfig {
|
|
||||||
}
|
|
||||||
*/
|
|
Loading…
Reference in new issue