jdk17 commit

This commit is contained in:
Eric
2026-02-09 13:29:54 +08:00
commit 167b0e02cf
292 changed files with 17485 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../../lingniu-framework-dependencies/pom.xml</relativePath>
</parent>
<artifactId>lingniu-framework-plugin-apollo</artifactId>
<name>${project.artifactId}</name>
<dependencies>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-util</artifactId>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
package cn.lingniu.framework.plugin.apollo.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = ApolloConfig.PRE_FIX)
public class ApolloConfig {
public final static String PRE_FIX = "framework.lingniu.apollo";
/**
* 是否开始Apollo配置
*/
private Boolean enabled = true;
/**
* Meta地址
*/
private String meta;
/**
* 配置文件列表 以,分割
*/
private String namespaces = "";
/**
* 无需配置 app.id 等于 spring.application.name
*/
private String appId;
}

View File

@@ -0,0 +1,79 @@
package cn.lingniu.framework.plugin.apollo.extend;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import com.ctrip.framework.apollo.spring.annotation.ApolloProcessor;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
/**
* Apollo Annotation Processor for Spring Application
*
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloAnnotationProcessor extends ApolloProcessor {
@Override
protected void processField(Object bean, String beanName, 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);
String namespace = System.getProperty("apollo.bootstrap.namespaces", annotation.value());
Config config = ConfigService.getConfig(namespace);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, bean, config);
}
@Override
protected void processMethod(final Object bean, String beanName, 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 namespaceProperties = System.getProperty("apollo.bootstrap.namespaces", String.join(",", annotation.value()));
String[] namespaces = namespaceProperties.split(",");
String[] annotatedInterestedKeys = annotation.interestedKeys();
String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
ConfigChangeListener configChangeListener = 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) {
Config config = ConfigService.getConfig(namespace);
if (interestedKeys == null && interestedKeyPrefixes == null) {
config.addChangeListener(configChangeListener);
} else {
config.addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
}
}
}
}

View File

@@ -0,0 +1,58 @@
package cn.lingniu.framework.plugin.apollo.extend;
import cn.lingniu.framework.plugin.util.validation.ObjectEmptyUtils;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ApolloConfigChangeLogListener implements ApplicationContextAware {
@Resource
RefreshScope refreshScope;
private ApplicationContext applicationContext;
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
if (log.isInfoEnabled()) {
for (String changedKey : changeEvent.changedKeys()) {
ConfigChange changeInfo = changeEvent.getChange(changedKey);
if (ObjectEmptyUtils.isEmpty(changeInfo)) {
continue;
}
log.info("【apollo 配置变更】 - namespace: {}, property: {}, oldValue: {}, newValue: {}, changeType: {}",
changeInfo.getNamespace(), changeInfo.getPropertyName(),
changeInfo.getOldValue(), changeInfo.getNewValue(), changeInfo.getChangeType());
}
}
applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
refreshProperties(changeEvent);
}
public void refreshProperties(ConfigChangeEvent changeEvent) {
try {
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
if (ObjectEmptyUtils.isNotEmpty(refreshScope)) {
refreshScope.refreshAll();
}
} catch (Exception e) {
log.error("Failed to refresh properties after Apollo config change", e);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

View File

@@ -0,0 +1,26 @@
package cn.lingniu.framework.plugin.apollo.extend;
import javassist.ClassPool;
import javassist.LoaderClassPath;
public class ClassPoolUtils {
private static volatile ClassPool instance;
private ClassPoolUtils() {
}
public static ClassPool getInstance() {
if (instance == null) {
synchronized (ClassPoolUtils.class) {
if (instance == null) {
instance = ClassPool.getDefault();
instance.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
}
}
}
return instance;
}
}

View File

@@ -0,0 +1,47 @@
package cn.lingniu.framework.plugin.apollo.extend;
import com.ctrip.framework.apollo.core.spi.Ordered;
import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor;
import com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener;
import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor;
import com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper;
import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import java.util.HashMap;
import java.util.Map;
public class FramewokConfigPropertySourcesProcessorHelper implements ConfigPropertySourcesProcessorHelper {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap<>();
// to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer
propertySourcesPlaceholderPropertyValues.put("order", 0);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class,
propertySourcesPlaceholderPropertyValues);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, AutoUpdateConfigChangeListener.class);//
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, FrameworkApolloAnnotationProcessor.class); //扩展 Apollo 注解处理器
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class);
processSpringValueDefinition(registry);
}
/**
* For Spring 3.x versions, the BeanDefinitionRegistryPostProcessor would not be instantiated if
* it is added in postProcessBeanDefinitionRegistry phase, so we have to manually call the
* postProcessBeanDefinitionRegistry method of SpringValueDefinitionProcessor here...
*/
private void processSpringValueDefinition(BeanDefinitionRegistry registry) {
SpringValueDefinitionProcessor springValueDefinitionProcessor = new SpringValueDefinitionProcessor();
springValueDefinitionProcessor.postProcessBeanDefinitionRegistry(registry);
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 10 ; // 优先级放高
}
}

View File

@@ -0,0 +1,265 @@
package cn.lingniu.framework.plugin.apollo.extend;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.ctrip.framework.apollo.spring.annotation.ApolloProcessor;
import com.ctrip.framework.apollo.spring.property.PlaceholderHelper;
import com.ctrip.framework.apollo.spring.property.SpringValue;
import com.ctrip.framework.apollo.spring.property.SpringValueRegistry;
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Apollo Annotation Processor for Spring Application
*/
public class FrameworkApolloAnnotationProcessor extends ApolloProcessor implements BeanFactoryAware,
EnvironmentAware {
private static final Logger logger = LoggerFactory.getLogger(ApolloAnnotationProcessor.class);
private static final String NAMESPACE_DELIMITER = ",";
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(NAMESPACE_DELIMITER)
.omitEmptyStrings().trimResults();
private static final Map<String, Gson> DATEPATTERN_GSON_MAP = new ConcurrentHashMap<>();
private final ConfigUtil configUtil; // 配置工具类
private final PlaceholderHelper placeholderHelper;
private final SpringValueRegistry springValueRegistry;
/**
* resolve the expression.
*/
private ConfigurableBeanFactory configurableBeanFactory;
private Environment environment;
public FrameworkApolloAnnotationProcessor() {
configUtil = ApolloInjector.getInstance(ConfigUtil.class);
placeholderHelper = SpringInjector.getInstance(PlaceholderHelper.class);
springValueRegistry = SpringInjector.getInstance(SpringValueRegistry.class);
}
@Override
protected void processField(Object bean, String beanName, Field field) {
this.processApolloConfig(bean, field);
this.processApolloJsonValue(bean, beanName, field);
}
// 处理Bean方法上的Apollo注解
@Override
protected void processMethod(final Object bean, String beanName, final Method method) {
this.processApolloConfigChangeListener(bean, method);
this.processApolloJsonValue(bean, beanName, method);
}
// field-具体注解处理方法--处理@ApolloConfig字段注解
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 appId = StringUtils.defaultIfBlank(annotation.appId(), configUtil.getAppId());
final String namespace = annotation.value();
final String resolvedAppId = this.environment.resolveRequiredPlaceholders(appId);
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
Config config = ConfigService.getConfig(resolvedAppId, 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 appId = StringUtils.defaultIfBlank(annotation.appId(), configUtil.getAppId());
String namespaceProperties =System.getProperty("apollo.bootstrap.namespaces",String.join( "," ,annotation.value())); //todo 默认处理所有-bootstrap.namespaces
String[] namespaces = namespaceProperties.split(",");
String[] annotatedInterestedKeys = annotation.interestedKeys();
String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
ConfigChangeListener configChangeListener = 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;
Set<String> resolvedNamespaces = processResolveNamespaceValue(namespaces);
for (String namespace : resolvedNamespaces) {
Config config = ConfigService.getConfig(appId, namespace);
if (interestedKeys == null && interestedKeyPrefixes == null) {
config.addChangeListener(configChangeListener);
} else {
config.addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
}
}
}
/**
* Evaluate and resolve namespaces from env/properties.
* Split delimited namespaces
* @param namespaces
* @return resolved namespaces
*/
private Set<String> processResolveNamespaceValue(String[] namespaces) {
Set<String> resolvedNamespaces = new HashSet<>();
for (String namespace : namespaces) {
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
if (resolvedNamespace.contains(NAMESPACE_DELIMITER)) {
resolvedNamespaces.addAll(NAMESPACE_SPLITTER.splitToList(resolvedNamespace));
} else {
resolvedNamespaces.add(resolvedNamespace);
}
}
return resolvedNamespaces;
}
private void processApolloJsonValue(Object bean, String beanName, Field field) {
ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(field, ApolloJsonValue.class);
if (apolloJsonValue == null) {
return; // 处理方法上的@ApolloJsonValue注解
}
String placeholder = apolloJsonValue.value();
String datePattern = apolloJsonValue.datePattern();
Object propertyValue = this.resolvePropertyValue(beanName, placeholder);
if (propertyValue == null) {
return;
}
boolean accessible = field.isAccessible();
field.setAccessible(true);
ReflectionUtils
.setField(field, bean, parseJsonValue((String) propertyValue, field.getGenericType(), datePattern));
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();
String datePattern = apolloJsonValue.datePattern();
Object propertyValue = this.resolvePropertyValue(beanName, placeHolder);
if (propertyValue == null) {
return;
}
Type[] types = method.getGenericParameterTypes();
Preconditions.checkArgument(types.length == 1,
"Ignore @ApolloJsonValue setter {}.{}, expecting 1 parameter, actual {} parameters",
bean.getClass().getName(), method.getName(), method.getParameterTypes().length);
boolean accessible = method.isAccessible();
method.setAccessible(true); // 解析占位符获取JSON值
ReflectionUtils.invokeMethod(method, bean, parseJsonValue((String) propertyValue, types[0], datePattern));
method.setAccessible(accessible);
if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeHolder);
for (String key : keys) {
SpringValue springValue = new SpringValue(key, placeHolder, bean, beanName, method, true);
springValueRegistry.register(this.configurableBeanFactory, key, springValue);
logger.debug("Monitoring {}", springValue);
}
}
}
private Object resolvePropertyValue(String beanName, String placeHolder) {
Object propertyValue = placeholderHelper
.resolvePropertyValue(this.configurableBeanFactory, beanName, placeHolder);
// propertyValue will never be null, as @ApolloJsonValue will not allow that
if (!(propertyValue instanceof String)) {
return null;
}
return propertyValue;
}
private Object parseJsonValue(String json, Type targetType, String datePattern) {
try {
return DATEPATTERN_GSON_MAP.computeIfAbsent(datePattern, this::buildGson).fromJson(json, targetType);
} catch (Throwable ex) {
logger.error("Parsing json '{}' to type {} failed!", json, targetType, ex);
throw ex;
}
}
private Gson buildGson(String datePattern) {
if (StringUtils.isBlank(datePattern)) {
return new Gson();
}
return new GsonBuilder().setDateFormat(datePattern).create();
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}

View File

@@ -0,0 +1,118 @@
package cn.lingniu.framework.plugin.apollo.extend;
import com.ctrip.framework.apollo.build.ApolloInjector;
import com.ctrip.framework.apollo.core.spi.Ordered;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor;
import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor;
import com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener;
import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor;
import com.ctrip.framework.apollo.spring.spi.DefaultApolloConfigRegistrarHelper;
import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import java.util.HashMap;
import java.util.Map;
public class FrameworkApolloConfigRegistrarHelper implements com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper, Ordered {
private static final Logger logger = LoggerFactory.getLogger(
DefaultApolloConfigRegistrarHelper.class);
private final ConfigUtil configUtil = ApolloInjector.getInstance(ConfigUtil.class);
private Environment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(importingClassMetadata.getAnnotationAttributes(EnableApolloConfig.class.getName()));
final String[] namespaces = System.getProperty("apollo.bootstrap.namespaces","application").split(","); //todo 默认处理所有-bootstrap.namespaces
final int order = attributes.getNumber("order");
// put main appId
PropertySourcesProcessor.addNamespaces(configUtil.getAppId(), Lists.newArrayList(this.resolveNamespaces(namespaces)), order);
// put multiple appId into
AnnotationAttributes[] multipleConfigs = attributes.getAnnotationArray("multipleConfigs");
if (multipleConfigs != null) {
for (AnnotationAttributes multipleConfig : multipleConfigs) {
String appId = multipleConfig.getString("appId");
String[] multipleNamespaces = this.resolveNamespaces(multipleConfig.getStringArray("namespaces"));
String secret = resolveSecret(multipleConfig.getString("secret"));
int multipleOrder = multipleConfig.getNumber("order");
// put multiple secret into system property
if (!StringUtils.isBlank(secret)) {
System.setProperty("apollo.accesskey." + appId + ".secret", secret);
}
PropertySourcesProcessor.addNamespaces(appId, Lists.newArrayList(multipleNamespaces), multipleOrder);
}
}
Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap<>();
// to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer
propertySourcesPlaceholderPropertyValues.put("order", 0);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class,
propertySourcesPlaceholderPropertyValues); // 属性占位符配置器
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, AutoUpdateConfigChangeListener.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, FrameworkApolloAnnotationProcessor.class); //todo 扩展的Apollo 注解处理器
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class);
}
private String[] resolveNamespaces(String[] namespaces) {
// no support for Spring version prior to 3.2.x, see https://github.com/apolloconfig/apollo/issues/4178
if (this.environment == null) {
logNamespacePlaceholderNotSupportedMessage(namespaces);
return namespaces;
}
String[] resolvedNamespaces = new String[namespaces.length];
for (int i = 0; i < namespaces.length; i++) {
// throw IllegalArgumentException if given text is null or if any placeholders are unresolvable
resolvedNamespaces[i] = this.environment.resolveRequiredPlaceholders(namespaces[i]);
}
return resolvedNamespaces;
}
private String resolveSecret(String secret){
if (this.environment == null) {
if (secret != null && secret.contains("${")) {
logger.warn("secret placeholder {} is not supported for Spring version prior to 3.2.x", secret);
}
return secret;
}
return this.environment.resolveRequiredPlaceholders(secret);
}
private void logNamespacePlaceholderNotSupportedMessage(String[] namespaces) {
for (String namespace : namespaces) {
if (namespace.contains("${")) {
logger.warn("Namespace placeholder {} is not supported for Spring version prior to 3.2.x,"
+ " see https://github.com/apolloconfig/apollo/issues/4178 for more details.",
namespace);
break;
}
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 10;
}
@Override
public void setEnvironment(Environment environment) {
}
}

View File

@@ -0,0 +1,26 @@
package cn.lingniu.framework.plugin.apollo.init;
import cn.lingniu.framework.plugin.apollo.extend.ApolloConfigChangeLogListener;
import cn.lingniu.framework.plugin.apollo.config.ApolloConfig;
import cn.lingniu.framework.plugin.util.config.PropertyUtils;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Slf4j
@Configuration
@EnableApolloConfig
@ConditionalOnProperty(prefix = ApolloConfig.PRE_FIX, name = "enabled", havingValue = "true")
@Import({ApolloConfigChangeLogListener.class})
public class ApolloAutoConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() {
log.info("Apollo configuration enabled(启动), meta URL: {}", PropertyUtils.getProperty("apollo.meta"));
}
}

View File

@@ -0,0 +1,82 @@
package cn.lingniu.framework.plugin.apollo.init;
import cn.lingniu.framework.plugin.apollo.config.ApolloConfig;
import cn.lingniu.framework.plugin.apollo.extend.ClassPoolUtils;
import cn.lingniu.framework.plugin.core.config.CommonConstant;
import cn.lingniu.framework.plugin.core.context.ApplicationNameContext;
import cn.lingniu.framework.plugin.util.validation.ObjectEmptyUtils;
import cn.lingniu.framework.plugin.util.config.PropertyUtils;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import java.io.File;
/**
* apollo 初始化
*/
@Slf4j
@Order(Integer.MIN_VALUE + 100)
public class ApolloInit implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private String applicationName;
private final static String AppId = "app.id";
private final static String ApolloMeta = "apollo.meta";
private final static String ApolloBootstrapEnabled = "apollo.bootstrap.enabled";
private final static String ApolloBootstrapEagerLoadEnabled = "apollo.bootstrap.eagerLoad.enabled";
private final static String UserDir = "user.dir";
public final static String NameSpaces = "framework.lingniu.apollo.namespaces";
public final static String FrameworkMeta = "framework.lingniu.apollo.meta";
public final static String FrameworkEnabled = "framework.lingniu.apollo.enabled";
private final static String APOLLO_NAME = ApolloConfig.PRE_FIX + ".name";
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
applicationName = environment.getProperty(APOLLO_NAME, environment.getProperty(CommonConstant.SPRING_APP_NAME_KEY));
String profile = environment.getProperty(CommonConstant.ACTIVE_PROFILES_PROPERTY);
this.initApolloConfig(environment, applicationName, profile);
}
void initApolloConfig(ConfigurableEnvironment environment, String appName, String profile) {
//优先原始配置
if (!ObjectEmptyUtils.isEmpty(environment.getProperty(ApolloBootstrapEnabled))
&& !ObjectEmptyUtils.isEmpty(environment.getProperty(ApolloMeta))
&& !ObjectEmptyUtils.isEmpty(environment.getProperty(AppId))) {
return;
}
if (ObjectEmptyUtils.isEmpty(environment.getProperty(FrameworkEnabled)) || environment.getProperty(FrameworkEnabled).equalsIgnoreCase("false")) {
setDefaultProperty(ApolloBootstrapEnabled, "false");
setDefaultProperty(ApolloBootstrapEagerLoadEnabled, "false");
return;
}
PropertyUtils.setDefaultInitProperty("app.id", "test-ln");
// PropertyUtils.setDefaultInitProperty("app.id", appName);
setDefaultProperty("apollo.meta", environment.getProperty(FrameworkMeta));
setDefaultProperty("apollo.bootstrap.enabled", "true");
setDefaultProperty("apollo.bootstrap.namespaces", environment.getProperty(NameSpaces, "application"));
setDefaultProperty("apollo.bootstrap.eagerLoad.enabled", "true");
setDefaultProperty("spring.boot.enableautoconfiguration", "true");
setDefaultProperty("env",profile.toUpperCase());
setDefaultProperty("apollo.cache-dir", System.getProperty(UserDir) + File.separator + "apolloConfig" + File.separator);
}
void setDefaultProperty(String key, String defaultPropertyValue) {
PropertyUtils.setDefaultInitProperty(key, defaultPropertyValue);
}
}

View File

@@ -0,0 +1 @@
cn.lingniu.framework.plugin.apollo.extend.FrameworkApolloConfigRegistrarHelper

View File

@@ -0,0 +1 @@
cn.lingniu.framework.plugin.apollo.extend.FramewokConfigPropertySourcesProcessorHelper

View File

@@ -0,0 +1,2 @@
org.springframework.context.ApplicationContextInitializer=\
cn.lingniu.framework.plugin.apollo.init.ApolloInit

View File

@@ -0,0 +1,37 @@
# 【重要】apllo服务搭建、和详细demo使用教程---参考官网
## 概述 (Overview)
1. 定位:基于 Apollo 封装的分布式配置管理中心组件
2. 核心能力
* 集中化配置管理:统一管理不同环境、不同集群的配置
* 实时推送更新:配置变更后实时推送到应用端,无需重启服务
* 多环境支持:支持开发、测试、生产等多套环境配置隔离
3. 适用场景
* 微服务架构下的配置管理
* 多环境、多集群的应用配置管理
* 需要动态调整配置参数的业务场
* 对配置变更实时性要求较高的系统
## 如何配置--参考ApolloConfig类
```yaml
framework:
lingniu:
apollo:
#namespaces必须配置配置文件列表以逗号分割
namespaces: application,applicationTest
# 是否开启 Apollo 配置默认true
enabled: true
# appId 等于 spring.application.name无需配置
appId: lingniu-framework-demo
# meta 地址,框架自动获取,无需配置
meta: http://xxx:8180
```
## 核心参数描述
- app.id此参数未配置默认采用spring.application.name
- framework.lingniu.apollo.meta 为apollo的eurka注册地址
- framework.lingniu.apollo.enabled是否启用
- framework.lingniu.apollo.namespaces 可配置多个配置文件