sentinel-starter support datasource & refactor some classes

pull/898/head
fangjian0423 7 years ago
parent 322ead8d76
commit 5394eb89fb

@ -31,6 +31,21 @@
<artifactId>sentinel-datasource-extension</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-zookeeper</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>${sentinel.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
@ -67,6 +82,13 @@
<version>${project.version}</version>
</dependency>
<!-- Own dependencies - Sentinel-Dubbo-Api -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>sentinel-dubbo-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Testing Dependencies -->

@ -25,6 +25,29 @@
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-zookeeper</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>

@ -0,0 +1,33 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel;
/**
* @author fangjian
*/
public interface SentinelConstants {
String PROPERTY_PREFIX = "spring.cloud.sentinel";
String PROPERTY_ITEM_SEPARATOR = ".";
String PROPERTY_DATASOURCE_NAME = "datasource";
String PROPERTY_DATASOURCE_PREFIX = PROPERTY_PREFIX + PROPERTY_ITEM_SEPARATOR
+ PROPERTY_DATASOURCE_NAME;
}

@ -26,7 +26,7 @@ import org.springframework.core.Ordered;
* @author xiaojing
* @author hengyunabc
*/
@ConfigurationProperties(prefix = "spring.cloud.sentinel")
@ConfigurationProperties(prefix = SentinelConstants.PROPERTY_PREFIX)
public class SentinelProperties {
/**

@ -19,59 +19,37 @@ package org.springframework.cloud.alibaba.sentinel;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.servlet.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
/**
* @author xiaojing
*/
@Configuration
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true)
@EnableConfigurationProperties(SentinelProperties.class)
public class SentinelWebAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(SentinelWebAutoConfiguration.class);
@Value("${project.name:${spring.application.name:}}")
private String projectName;
@Autowired
private SentinelProperties properties;
public static final String APP_NAME = "project.name";
@PostConstruct
private void init() {
if (StringUtils.isEmpty(System.getProperty(APP_NAME))) {
System.setProperty(APP_NAME, projectName);
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))) {
System.setProperty(TransportConfig.SERVER_PORT, properties.getPort());
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))) {
System.setProperty(TransportConfig.CONSOLE_SERVER, properties.getDashboard());
}
}
@Bean
@ConditionalOnWebApplication
public FilterRegistrationBean<Filter> servletRequestListener() {
public FilterRegistrationBean servletRequestListener() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
SentinelProperties.Filter filterConfig = properties.getFilter();

@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel.annotation;
import java.lang.annotation.*;
import org.springframework.core.annotation.AliasFor;
/**
* An annotation to inject {@link com.alibaba.csp.sentinel.datasource.DataSource} instance
* into a Spring Bean. The Properties of DataSource bean get from config files with
* specific prefix.
*
* @author fangjian
* @see com.alibaba.csp.sentinel.datasource.DataSource
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SentinelDataSource {
@AliasFor("prefix")
String value() default "";
@AliasFor("value")
String prefix() default "";
String name() default ""; // spring bean name
}

@ -16,20 +16,52 @@
package org.springframework.cloud.alibaba.sentinel.custom;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.AppNameUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
import org.springframework.cloud.alibaba.sentinel.datasource.SentinelDataSourcePostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import javax.annotation.PostConstruct;
/**
* @author xiaojing
*/
@Configuration
@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true)
@EnableConfigurationProperties(SentinelProperties.class)
public class SentinelAutoConfiguration {
@Value("${project.name:${spring.application.name:}}")
private String projectName;
@Autowired
private SentinelProperties properties;
@PostConstruct
private void init() {
if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME))) {
System.setProperty(AppNameUtil.APP_NAME, projectName);
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))) {
System.setProperty(TransportConfig.SERVER_PORT, properties.getPort());
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))) {
System.setProperty(TransportConfig.CONSOLE_SERVER, properties.getDashboard());
}
}
@Bean
@ConditionalOnMissingBean
public SentinelResourceAspect sentinelResourceAspect() {
@ -38,9 +70,15 @@ public class SentinelAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(value = RestTemplate.class)
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
public SentinelBeanPostProcessor sentinelBeanPostProcessor() {
return new SentinelBeanPostProcessor();
}
@Bean
@ConditionalOnMissingBean
public SentinelDataSourcePostProcessor sentinelDataSourcePostProcessor() {
return new SentinelDataSourcePostProcessor();
}
}

@ -43,7 +43,7 @@ import com.alibaba.csp.sentinel.util.StringUtil;
*/
public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor {
private static final Logger LOGGER = LoggerFactory
private static final Logger logger = LoggerFactory
.getLogger(SentinelProtectInterceptor.class);
private SentinelProtect sentinelProtect;
@ -68,12 +68,12 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
response = execution.execute(request, body);
}
catch (BlockException e) {
LOGGER.error("RestTemplate block", e);
logger.error("RestTemplate block", e);
try {
handleBlockException(e);
}
catch (Exception ex) {
LOGGER.error("sentinel handle BlockException error.", e);
logger.error("sentinel handle BlockException error.", e);
}
}
finally {

@ -0,0 +1,151 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel.datasource;
import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.alibaba.csp.sentinel.datasource.DataSource;
/**
* {@link DataSource} Loader
*
* @author fangjian
*/
public class DataSourceLoader {
private static final Logger logger = LoggerFactory.getLogger(DataSourceLoader.class);
private final static String PROPERTIES_RESOURCE_LOCATION = "META-INF/sentinel-datasource.properties";
private final static String ALL_PROPERTIES_RESOURCES_LOCATION = CLASSPATH_ALL_URL_PREFIX
+ PROPERTIES_RESOURCE_LOCATION;
private final static ConcurrentMap<String, Class<? extends DataSource>> dataSourceClassesCache = new ConcurrentHashMap<String, Class<? extends DataSource>>(
4);
static void loadAllDataSourceClassesCache() {
Map<String, Class<? extends DataSource>> dataSourceClassesMap = loadAllDataSourceClassesCache(
ALL_PROPERTIES_RESOURCES_LOCATION);
dataSourceClassesCache.putAll(dataSourceClassesMap);
}
static Map<String, Class<? extends DataSource>> loadAllDataSourceClassesCache(
String resourcesLocation) {
Map<String, Class<? extends DataSource>> dataSourcesMap = new HashMap<String, Class<? extends DataSource>>(
4);
ClassLoader classLoader = DataSourceLoader.class.getClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
Resource[] resources = resolver.getResources(resourcesLocation);
for (Resource resource : resources) {
if (resource.exists()) {
Properties properties = PropertiesLoaderUtils
.loadProperties(resource);
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
String type = (String) entry.getKey();
String className = (String) entry.getValue();
if (!ClassUtils.isPresent(className, classLoader)) {
if (logger.isDebugEnabled()) {
logger.debug(
"Sentinel DataSource implementation [ type : "
+ type + ": , class : " + className
+ " , url : " + resource.getURL()
+ "] was not present in current classpath , "
+ "thus loading will be ignored , please add dependency if required !");
}
continue;
}
Assert.isTrue(!dataSourcesMap.containsKey(type),
"The duplicated type[" + type
+ "] of SentinelDataSource were found in "
+ "resource [" + resource.getURL() + "]");
Class<?> dataSourceClass = ClassUtils.resolveClassName(className,
classLoader);
Assert.isAssignable(DataSource.class, dataSourceClass);
dataSourcesMap.put(type,
(Class<? extends DataSource>) dataSourceClass);
if (logger.isDebugEnabled()) {
logger.debug("Sentinel DataSource implementation [ type : "
+ type + ": , class : " + className
+ "] was loaded.");
}
}
}
}
}
catch (IOException e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
return dataSourcesMap;
}
public static Class<? extends DataSource> loadClass(String type)
throws IllegalArgumentException {
Class<? extends DataSource> dataSourceClass = dataSourceClassesCache.get(type);
if (dataSourceClass == null) {
if (dataSourceClassesCache.isEmpty()) {
loadAllDataSourceClassesCache();
dataSourceClass = dataSourceClassesCache.get(type);
}
}
if (dataSourceClass == null) {
throw new IllegalArgumentException(
"Sentinel DataSource implementation [ type : " + type
+ " ] can't be found!");
}
return dataSourceClass;
}
}

@ -0,0 +1,217 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel.datasource;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotation;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.cloud.alibaba.sentinel.SentinelConstants;
import org.springframework.cloud.alibaba.sentinel.annotation.SentinelDataSource;
import org.springframework.cloud.alibaba.sentinel.util.PropertySourcesUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import com.alibaba.csp.sentinel.datasource.ConfigParser;
/**
* {@link SentinelDataSource @SentinelDataSource} Post Processor
*
* @author fangjian
* @see com.alibaba.csp.sentinel.datasource.DataSource
* @see SentinelDataSource
*/
public class SentinelDataSourcePostProcessor
extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor {
private static final Logger logger = LoggerFactory
.getLogger(SentinelDataSourcePostProcessor.class);
@Autowired
private ApplicationContext applicationContext;
@Autowired
private ConfigurableEnvironment environment;
private final Map<String, List<SentinelDataSourceField>> dataSourceFieldCache = new ConcurrentHashMap<>(
64);
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {
// find all fields using by @SentinelDataSource annotation
ReflectionUtils.doWithFields(beanType, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field)
throws IllegalArgumentException, IllegalAccessException {
SentinelDataSource annotation = getAnnotation(field,
SentinelDataSource.class);
if (annotation != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn(
"@SentinelDataSource annotation is not supported on static fields: "
+ field);
}
return;
}
if (dataSourceFieldCache.containsKey(beanName)) {
dataSourceFieldCache.get(beanName)
.add(new SentinelDataSourceField(annotation, field));
}
else {
List<SentinelDataSourceField> list = new ArrayList<>();
list.add(new SentinelDataSourceField(annotation, field));
dataSourceFieldCache.put(beanName, list);
}
}
}
});
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeanCreationException {
if (dataSourceFieldCache.containsKey(beanName)) {
List<SentinelDataSourceField> sentinelDataSourceFields = dataSourceFieldCache
.get(beanName);
sentinelDataSourceFields.forEach(sentinelDataSourceField -> {
try {
// construct DataSource field annotated by @SentinelDataSource
Field field = sentinelDataSourceField.getField();
ReflectionUtils.makeAccessible(field);
String dataSourceBeanName = constructDataSource(
sentinelDataSourceField.getSentinelDataSource());
field.set(bean, applicationContext.getBean(dataSourceBeanName));
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
});
}
return pvs;
}
private String constructDataSource(SentinelDataSource annotation) {
String prefix = annotation.value();
if (StringUtils.isEmpty(prefix)) {
prefix = SentinelConstants.PROPERTY_DATASOURCE_PREFIX;
}
Map<String, Object> propertyMap = PropertySourcesUtils
.getSubProperties(environment.getPropertySources(), prefix);
String alias = propertyMap.get("type").toString();
Class dataSourceClass = DataSourceLoader.loadClass(alias);
String beanName = StringUtils.isEmpty(annotation.name())
? StringUtils.uncapitalize(dataSourceClass.getSimpleName()) + "_" + prefix
: annotation.name();
if (applicationContext.containsBean(beanName)) {
return beanName;
}
Class targetClass = null;
// if alias exists in SentinelDataSourceRegistry, wired properties into
// FactoryBean
if (SentinelDataSourceRegistry.checkFactoryBean(alias)) {
targetClass = SentinelDataSourceRegistry.getFactoryBean(alias);
}
else {
// if alias not exists in SentinelDataSourceRegistry, wired properties into
// raw class
targetClass = dataSourceClass;
}
registerDataSource(beanName, targetClass, propertyMap);
return beanName;
}
private void registerDataSource(String beanName, Class targetClass,
Map<String, Object> propertyMap) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(targetClass);
for (String propertyName : propertyMap.keySet()) {
Field field = ReflectionUtils.findField(targetClass, propertyName);
if (field != null) {
if (field.getType().isAssignableFrom(ConfigParser.class)) {
// ConfigParser get from ApplicationContext
builder.addPropertyReference(propertyName,
propertyMap.get(propertyName).toString());
}
else {
// wired properties
builder.addPropertyValue(propertyName, propertyMap.get(propertyName));
}
}
}
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
beanFactory.registerBeanDefinition(beanName, builder.getBeanDefinition());
}
class SentinelDataSourceField {
private SentinelDataSource sentinelDataSource;
private Field field;
public SentinelDataSourceField(SentinelDataSource sentinelDataSource,
Field field) {
this.sentinelDataSource = sentinelDataSource;
this.field = field;
}
public SentinelDataSource getSentinelDataSource() {
return sentinelDataSource;
}
public void setSentinelDataSource(SentinelDataSource sentinelDataSource) {
this.sentinelDataSource = sentinelDataSource;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
}
}

@ -0,0 +1,67 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel.datasource;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean;
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.FileRefreshableDataSourceFactoryBean;
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.NacosDataSourceFactoryBean;
import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.ZookeeperDataSourceFactoryBean;
/**
* Registry to save DataSource FactoryBean
*
* @author fangjian
* @see com.alibaba.csp.sentinel.datasource.DataSource
* @see FileRefreshableDataSourceFactoryBean
* @see ZookeeperDataSourceFactoryBean
* @see NacosDataSourceFactoryBean
* @see ApolloDataSourceFactoryBean
*/
public class SentinelDataSourceRegistry {
private static ConcurrentHashMap<String, Class<? extends FactoryBean>> cache = new ConcurrentHashMap<>(
32);
static {
SentinelDataSourceRegistry.registerFactoryBean("file",
FileRefreshableDataSourceFactoryBean.class);
SentinelDataSourceRegistry.registerFactoryBean("zk",
ZookeeperDataSourceFactoryBean.class);
SentinelDataSourceRegistry.registerFactoryBean("nacos",
NacosDataSourceFactoryBean.class);
SentinelDataSourceRegistry.registerFactoryBean("apollo",
ApolloDataSourceFactoryBean.class);
}
public static synchronized void registerFactoryBean(String alias,
Class<? extends FactoryBean> clazz) {
cache.putIfAbsent(alias, clazz);
cache.put(alias, clazz);
}
public static Class<? extends FactoryBean> getFactoryBean(String alias) {
return cache.get(alias);
}
public static boolean checkFactoryBean(String alias) {
return cache.containsKey(alias);
}
}

@ -0,0 +1,61 @@
package org.springframework.cloud.alibaba.sentinel.datasource.factorybean;
import org.springframework.beans.factory.FactoryBean;
import com.alibaba.csp.sentinel.datasource.ConfigParser;
import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource;
/**
* @author fangjian
* @see ApolloDataSource
*/
public class ApolloDataSourceFactoryBean implements FactoryBean<ApolloDataSource> {
private String namespaceName;
private String flowRulesKey;
private String defaultFlowRuleValue;
private ConfigParser configParser;
@Override
public ApolloDataSource getObject() throws Exception {
return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue,
configParser);
}
@Override
public Class<?> getObjectType() {
return ApolloDataSource.class;
}
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public String getFlowRulesKey() {
return flowRulesKey;
}
public void setFlowRulesKey(String flowRulesKey) {
this.flowRulesKey = flowRulesKey;
}
public String getDefaultFlowRuleValue() {
return defaultFlowRuleValue;
}
public void setDefaultFlowRuleValue(String defaultFlowRuleValue) {
this.defaultFlowRuleValue = defaultFlowRuleValue;
}
public ConfigParser getConfigParser() {
return configParser;
}
public void setConfigParser(ConfigParser configParser) {
this.configParser = configParser;
}
}

@ -0,0 +1,74 @@
package org.springframework.cloud.alibaba.sentinel.datasource.factorybean;
import java.io.File;
import java.nio.charset.Charset;
import org.springframework.beans.factory.FactoryBean;
import com.alibaba.csp.sentinel.datasource.ConfigParser;
import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
/**
* @author fangjian
* @see FileRefreshableDataSource
*/
public class FileRefreshableDataSourceFactoryBean
implements FactoryBean<FileRefreshableDataSource> {
private String file;
private String charset;
private long recommendRefreshMs;
private int bufSize;
private ConfigParser configParser;
@Override
public FileRefreshableDataSource getObject() throws Exception {
return new FileRefreshableDataSource(new File(file), configParser,
recommendRefreshMs, bufSize, Charset.forName(charset));
}
@Override
public Class<?> getObjectType() {
return FileRefreshableDataSource.class;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public long getRecommendRefreshMs() {
return recommendRefreshMs;
}
public void setRecommendRefreshMs(long recommendRefreshMs) {
this.recommendRefreshMs = recommendRefreshMs;
}
public int getBufSize() {
return bufSize;
}
public void setBufSize(int bufSize) {
this.bufSize = bufSize;
}
public ConfigParser getConfigParser() {
return configParser;
}
public void setConfigParser(ConfigParser configParser) {
this.configParser = configParser;
}
}

@ -0,0 +1,60 @@
package org.springframework.cloud.alibaba.sentinel.datasource.factorybean;
import org.springframework.beans.factory.FactoryBean;
import com.alibaba.csp.sentinel.datasource.ConfigParser;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
/**
* @author fangjian
* @see NacosDataSource
*/
public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource> {
private String serverAddr;
private String groupId;
private String dataId;
private ConfigParser configParser;
@Override
public NacosDataSource getObject() throws Exception {
return new NacosDataSource(serverAddr, groupId, dataId, configParser);
}
@Override
public Class<?> getObjectType() {
return NacosDataSource.class;
}
public String getServerAddr() {
return serverAddr;
}
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getDataId() {
return dataId;
}
public void setDataId(String dataId) {
this.dataId = dataId;
}
public ConfigParser getConfigParser() {
return configParser;
}
public void setConfigParser(ConfigParser configParser) {
this.configParser = configParser;
}
}

@ -0,0 +1,80 @@
package org.springframework.cloud.alibaba.sentinel.datasource.factorybean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.FactoryBean;
import com.alibaba.csp.sentinel.datasource.ConfigParser;
import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;
/**
* @author fangjian
* @see ZookeeperDataSource
*/
public class ZookeeperDataSourceFactoryBean implements FactoryBean<ZookeeperDataSource> {
private String serverAddr;
private String path;
private String groupId;
private String dataId;
private ConfigParser configParser;
@Override
public ZookeeperDataSource getObject() throws Exception {
if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(dataId)) {
// the path will be /{groupId}/{dataId}
return new ZookeeperDataSource(serverAddr, groupId, dataId, configParser);
}
else {
// using path directly
return new ZookeeperDataSource(serverAddr, path, configParser);
}
}
@Override
public Class<?> getObjectType() {
return ZookeeperDataSource.class;
}
public String getServerAddr() {
return serverAddr;
}
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getDataId() {
return dataId;
}
public void setDataId(String dataId) {
this.dataId = dataId;
}
public ConfigParser getConfigParser() {
return configParser;
}
public void setConfigParser(ConfigParser configParser) {
this.configParser = configParser;
}
}

@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.cloud.alibaba.sentinel.util;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
/**
* {@link PropertySources} Utilities
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public abstract class PropertySourcesUtils {
/**
* Get Sub {@link Properties}
*
* @param propertySources {@link PropertySource} Iterable
* @param prefix the prefix of property name
* @return Map
* @see Properties
*/
public static Map<String, Object> getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix) {
Map<String, Object> subProperties = new LinkedHashMap<String, Object>();
String normalizedPrefix = normalizePrefix(prefix);
for (PropertySource<?> source : propertySources) {
if (source instanceof EnumerablePropertySource) {
for (String name : ((EnumerablePropertySource<?>) source).getPropertyNames()) {
if (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) {
String subName = name.substring(normalizedPrefix.length());
if (!subProperties.containsKey(subName)) { // take first one
Object value = source.getProperty(name);
subProperties.put(subName, value);
}
}
}
}
}
return subProperties;
}
/**
* Normalize the prefix
*
* @param prefix the prefix
* @return the prefix
*/
public static String normalizePrefix(String prefix) {
return prefix.endsWith(".") ? prefix : prefix + ".";
}
}

@ -0,0 +1,4 @@
nacos = com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource
file =com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource
apollo = com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource
zk = com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource

@ -15,6 +15,18 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
</dependency>
</dependencies>
</project>

Loading…
Cancel
Save