From 1d15cdaee5589be2641bc984573a3f4c4a211a6b Mon Sep 17 00:00:00 2001 From: fangjian0423 Date: Wed, 24 Oct 2018 10:38:23 +0800 Subject: [PATCH] Polish #51. Add a new module spring-cloud-alibaba-sentinel-datasource separate from spring-cloud-alibaba-sentinel. --- pom.xml | 2 +- spring-cloud-alibaba-dependencies/pom.xml | 5 + .../sentinel-core-example/readme-zh.md | 2 +- .../sentinel-core-example/readme.md | 3 +- .../pom.xml | 69 +++++ .../sentinel/datasource/DataSourceLoader.java | 152 ++++++++++ .../SentinelDataSourceConstants.java | 33 +++ .../SentinelDataSourcePostProcessor.java | 258 +++++++++++++++++ .../SentinelDataSourceRegistry.java | 7 +- .../annotation/SentinelDataSource.java | 4 +- .../ApolloDataSourceFactoryBean.java | 63 +++++ .../FileRefreshableDataSourceFactoryBean.java | 76 +++++ .../NacosDataSourceFactoryBean.java | 62 ++++ .../ZookeeperDataSourceFactoryBean.java | 81 ++++++ .../util/PropertySourcesUtils.java | 12 +- .../META-INF/sentinel-datasource.properties | 0 spring-cloud-alibaba-sentinel/pom.xml | 26 +- .../alibaba/sentinel/SentinelConstants.java | 7 - .../sentinel/datasource/DataSourceLoader.java | 151 ---------- .../SentinelDataSourcePostProcessor.java | 264 ------------------ .../ApolloDataSourceFactoryBean.java | 61 ---- .../FileRefreshableDataSourceFactoryBean.java | 74 ----- .../NacosDataSourceFactoryBean.java | 60 ---- .../ZookeeperDataSourceFactoryBean.java | 80 ------ .../pom.xml | 12 - 25 files changed, 818 insertions(+), 746 deletions(-) create mode 100644 spring-cloud-alibaba-sentinel-datasource/pom.xml create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java rename {spring-cloud-alibaba-sentinel => spring-cloud-alibaba-sentinel-datasource}/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java (91%) rename {spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel => spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource}/annotation/SentinelDataSource.java (91%) create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java create mode 100644 spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java rename {spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel => spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource}/util/PropertySourcesUtils.java (96%) rename {spring-cloud-alibaba-sentinel => spring-cloud-alibaba-sentinel-datasource}/src/main/resources/META-INF/sentinel-datasource.properties (100%) delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java delete mode 100644 spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java diff --git a/pom.xml b/pom.xml index 1353ad3e7..5b742e3dd 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ spring-cloud-alibaba-dependencies spring-cloud-alibaba-sentinel - + spring-cloud-alibaba-sentinel-datasource spring-cloud-alibaba-nacos-config spring-cloud-alibaba-nacos-discovery spring-cloud-alibaba-examples diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 167f71e9d..b253dd10a 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -95,6 +95,11 @@ spring-cloud-alibaba-sentinel ${project.version} + + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource + ${project.version} + org.springframework.cloud spring-cloud-alicloud-oss diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index 4c0b2aeba..c07c20e37 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -222,7 +222,7 @@ Sentinel starter 整合了目前存在的几类 DataSource。只需要在配置 `spring.cloud.sentinel.datasource.converter`代表 `Converter` 在 Spring 容器里的 name。如果没找到,会抛出异常。 -type目前支持file, nacos, zk, apollo。 +type目前支持file, nacos, zk, apollo。其中nacos,zk,apollo的使用需要加上对应的依赖`sentinel-datasource-nacos`, `sentinel-datasource-zookeeper`, `sentinel-datasource-apollo` ### 自定义DataSource diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md index a51ed38ad..dcdd77fc3 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md @@ -193,7 +193,8 @@ spring.cloud.sentinel.datasource.recommendRefreshMs means the recommendRefreshMs spring.cloud.sentinel.datasource.converter means the name of spring bean that type is Converter. If the bean is not exists, will throw exception. -Now datasource type support 4 categories: file, nacos, zk, apollo. +Now datasource type support 4 categories: file, nacos, zk, apollo. If you want to using nacos, zk or apollo, you should add `sentinel-datasource-nacos`, `sentinel-datasource-zookeeper` or `sentinel-datasource-apollo` dependency. + ### User-defined DataSource diff --git a/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-sentinel-datasource/pom.xml new file mode 100644 index 000000000..077e52615 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -0,0 +1,69 @@ + + + + + org.springframework.cloud + spring-cloud-alibaba + 0.2.0 + + 4.0.0 + + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource + Spring Cloud Alibaba Sentinel DataSource + + + + + com.alibaba.csp + sentinel-datasource-extension + + + + com.alibaba.csp + sentinel-datasource-nacos + provided + true + + + + com.alibaba.csp + sentinel-datasource-zookeeper + provided + true + + + + com.alibaba.csp + sentinel-datasource-apollo + provided + true + + + + + + org.springframework.boot + spring-boot + provided + true + + + + org.springframework.boot + spring-boot-autoconfigure + provided + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java new file mode 100644 index 000000000..40f17197d --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java @@ -0,0 +1,152 @@ +/* + * 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.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 com.alibaba.csp.sentinel.datasource.ReadableDataSource; + +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 static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; + +/** + * {@link ReadableDataSource} Loader + * + * @author Jim + */ +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> dataSourceClassesCache + = new ConcurrentHashMap>( + 4); + + static void loadAllDataSourceClassesCache() { + Map> dataSourceClassesMap = loadAllDataSourceClassesCache( + ALL_PROPERTIES_RESOURCES_LOCATION); + + dataSourceClassesCache.putAll(dataSourceClassesMap); + } + + static Map> loadAllDataSourceClassesCache( + String resourcesLocation) { + + Map> dataSourcesMap + = new HashMap>( + 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 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(ReadableDataSource.class, dataSourceClass); + + dataSourcesMap.put(type, + (Class)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 loadClass(String type) + throws IllegalArgumentException { + + Class 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; + + } + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java new file mode 100644 index 000000000..49549399f --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceConstants.java @@ -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.datasource; + +/** + * @author Jim + */ +public interface SentinelDataSourceConstants { + + 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; + +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java new file mode 100644 index 000000000..0a83db7a5 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java @@ -0,0 +1,258 @@ +/* + * 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.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 com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.ReadableDataSource; +import com.alibaba.csp.sentinel.property.SentinelProperty; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; +import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRule; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; + +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.boot.context.event.ApplicationStartedEvent; +import org.springframework.cloud.alibaba.sentinel.datasource.annotation.SentinelDataSource; +import org.springframework.cloud.alibaba.sentinel.datasource.util.PropertySourcesUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.event.EventListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; + +import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; + +/** + * {@link SentinelDataSource @SentinelDataSource} Post Processor + * + * @author Jim + * @see ReadableDataSource + * @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> 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 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 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 = SentinelDataSourceConstants.PROPERTY_DATASOURCE_PREFIX; + } + Map 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 propertyMap) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder + .genericBeanDefinition(targetClass); + for (String propertyName : propertyMap.keySet()) { + Field field = ReflectionUtils.findField(targetClass, propertyName); + if (field != null) { + if (field.getType().isAssignableFrom(Converter.class)) { + // Converter 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()); + } + + @EventListener(classes = ApplicationStartedEvent.class) + public void appStartedListener(ApplicationStartedEvent event) throws Exception { + Map dataSourceMap = event.getApplicationContext().getBeansOfType( + ReadableDataSource.class); + if (dataSourceMap.size() == 1) { + ReadableDataSource dataSource = dataSourceMap.values().iterator().next(); + Object ruleConfig = dataSource.loadConfig(); + SentinelProperty sentinelProperty = dataSource.getProperty(); + if (checkRuleType(ruleConfig, FlowRule.class)) { + FlowRuleManager.register2Property(sentinelProperty); + } + if (checkRuleType(ruleConfig, DegradeRule.class)) { + DegradeRuleManager.register2Property(sentinelProperty); + } + if (checkRuleType(ruleConfig, SystemRule.class)) { + SystemRuleManager.register2Property(sentinelProperty); + } + if (checkRuleType(ruleConfig, AuthorityRule.class)) { + AuthorityRuleManager.register2Property(sentinelProperty); + } + } + } + + private boolean checkRuleType(Object ruleConfig, Class type) { + if (ruleConfig.getClass() == type) { + return true; + } else if (ruleConfig instanceof List) { + List ruleList = (List)ruleConfig; + if (ruleList.stream().filter(rule -> rule.getClass() == type).toArray().length == ruleList.size()) { + return true; + } + } + return false; + } + + 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; + } + } + +} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java similarity index 91% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java index ceb90ee1f..5108196b5 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourceRegistry.java @@ -16,7 +16,7 @@ package org.springframework.cloud.alibaba.sentinel.datasource; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; import com.alibaba.csp.sentinel.datasource.ReadableDataSource; @@ -29,7 +29,7 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.Zookeep /** * Registry to save DataSource FactoryBean * - * @author fangjian + * @author Jim * @see ReadableDataSource * @see FileRefreshableDataSourceFactoryBean * @see ZookeeperDataSourceFactoryBean @@ -38,7 +38,7 @@ import org.springframework.cloud.alibaba.sentinel.datasource.factorybean.Zookeep */ public class SentinelDataSourceRegistry { - private static ConcurrentHashMap> cache = new ConcurrentHashMap<>( + private static HashMap> cache = new HashMap<>( 32); static { @@ -54,7 +54,6 @@ public class SentinelDataSourceRegistry { public static synchronized void registerFactoryBean(String alias, Class clazz) { - cache.putIfAbsent(alias, clazz); cache.put(alias, clazz); } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java similarity index 91% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java index 93ef1bdb9..b6b33226b 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/annotation/SentinelDataSource.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/annotation/SentinelDataSource.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.alibaba.sentinel.annotation; +package org.springframework.cloud.alibaba.sentinel.datasource.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -31,7 +31,7 @@ import org.springframework.core.annotation.AliasFor; * into a Spring Bean. The Properties of DataSource bean get from config files with * specific prefix. * - * @author fangjian + * Jim * @see ReadableDataSource */ @Target({ElementType.FIELD}) diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java new file mode 100644 index 000000000..e0df905b1 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java @@ -0,0 +1,63 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link ApolloDataSource} instance. + * + * @author Jim + * @see ApolloDataSource + */ +public class ApolloDataSourceFactoryBean implements FactoryBean { + + private String namespaceName; + private String flowRulesKey; + private String defaultFlowRuleValue; + private Converter converter; + + @Override + public ApolloDataSource getObject() throws Exception { + return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, + converter); + } + + @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 Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java new file mode 100644 index 000000000..c7b4771f3 --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java @@ -0,0 +1,76 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import java.io.File; +import java.nio.charset.Charset; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link FileRefreshableDataSource} instance. + * + * @author Jim + * @see FileRefreshableDataSource + */ +public class FileRefreshableDataSourceFactoryBean + implements FactoryBean { + + private String file; + private String charset; + private long recommendRefreshMs; + private int bufSize; + private Converter converter; + + @Override + public FileRefreshableDataSource getObject() throws Exception { + return new FileRefreshableDataSource(new File(file), converter, + 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 Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java new file mode 100644 index 000000000..12dbd138f --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -0,0 +1,62 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link NacosDataSource} instance. + * + * @author Jim + * @see NacosDataSource + */ +public class NacosDataSourceFactoryBean implements FactoryBean { + + private String serverAddr; + private String groupId; + private String dataId; + private Converter converter; + + @Override + public NacosDataSource getObject() throws Exception { + return new NacosDataSource(serverAddr, groupId, dataId, converter); + } + + @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 Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java new file mode 100644 index 000000000..8b4ed177e --- /dev/null +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java @@ -0,0 +1,81 @@ +package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; + +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} for creating {@link ZookeeperDataSource} instance. + * + * @author Jim + * @see ZookeeperDataSource + */ +public class ZookeeperDataSourceFactoryBean implements FactoryBean { + + private String serverAddr; + + private String path; + + private String groupId; + private String dataId; + + private Converter converter; + + @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, converter); + } else { + // using path directly + return new ZookeeperDataSource(serverAddr, path, converter); + } + } + + @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 Converter getConverter() { + return converter; + } + + public void setConverter(Converter Converter) { + this.converter = Converter; + } +} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java similarity index 96% rename from spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java rename to spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java index 6eafbd63b..fde8fc44f 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/util/PropertySourcesUtils.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/util/PropertySourcesUtils.java @@ -14,16 +14,16 @@ * 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; +package org.springframework.cloud.alibaba.sentinel.datasource.util; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.PropertySources; + /** * {@link PropertySources} Utilities * @@ -47,7 +47,7 @@ public abstract class PropertySourcesUtils { for (PropertySource source : propertySources) { if (source instanceof EnumerablePropertySource) { - for (String name : ((EnumerablePropertySource) source).getPropertyNames()) { + 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 diff --git a/spring-cloud-alibaba-sentinel/src/main/resources/META-INF/sentinel-datasource.properties b/spring-cloud-alibaba-sentinel-datasource/src/main/resources/META-INF/sentinel-datasource.properties similarity index 100% rename from spring-cloud-alibaba-sentinel/src/main/resources/META-INF/sentinel-datasource.properties rename to spring-cloud-alibaba-sentinel-datasource/src/main/resources/META-INF/sentinel-datasource.properties diff --git a/spring-cloud-alibaba-sentinel/pom.xml b/spring-cloud-alibaba-sentinel/pom.xml index 74b58421b..87f56fdba 100644 --- a/spring-cloud-alibaba-sentinel/pom.xml +++ b/spring-cloud-alibaba-sentinel/pom.xml @@ -27,35 +27,17 @@ com.alibaba.csp - sentinel-datasource-extension - - - - com.alibaba.csp - sentinel-datasource-nacos - true - - - - com.alibaba.csp - sentinel-datasource-zookeeper - true - - - - com.alibaba.csp - sentinel-datasource-apollo - true + sentinel-annotation-aspectj com.alibaba.csp - sentinel-annotation-aspectj + sentinel-dubbo-adapter - com.alibaba.csp - sentinel-dubbo-adapter + org.springframework.cloud + spring-cloud-alibaba-sentinel-datasource diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java index 747044a50..620445a4a 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/SentinelConstants.java @@ -23,11 +23,4 @@ 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; - } diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java deleted file mode 100644 index 068717660..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/DataSourceLoader.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.ReadableDataSource; - -/** - * {@link ReadableDataSource} 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> dataSourceClassesCache = new ConcurrentHashMap>( - 4); - - static void loadAllDataSourceClassesCache() { - Map> dataSourceClassesMap = loadAllDataSourceClassesCache( - ALL_PROPERTIES_RESOURCES_LOCATION); - - dataSourceClassesCache.putAll(dataSourceClassesMap); - } - - static Map> loadAllDataSourceClassesCache( - String resourcesLocation) { - - Map> dataSourcesMap = new HashMap>( - 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 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(ReadableDataSource.class, dataSourceClass); - - dataSourcesMap.put(type, - (Class) 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 loadClass(String type) - throws IllegalArgumentException { - - Class 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; - - } - -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java deleted file mode 100644 index 627c5be03..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/SentinelDataSourcePostProcessor.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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.boot.context.event.ApplicationStartedEvent; -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.context.event.EventListener; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.ReadableDataSource; -import com.alibaba.csp.sentinel.property.SentinelProperty; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; -import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; -import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.system.SystemRule; -import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; - -/** - * {@link SentinelDataSource @SentinelDataSource} Post Processor - * - * @author fangjian - * @see com.alibaba.csp.sentinel.datasource.ReadableDataSource - * @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> 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 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 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 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 propertyMap) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(targetClass); - for (String propertyName : propertyMap.keySet()) { - Field field = ReflectionUtils.findField(targetClass, propertyName); - if (field != null) { - if (field.getType().isAssignableFrom(Converter.class)) { - // Converter 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()); - } - - - @EventListener(classes = ApplicationStartedEvent.class) - public void appStartedListener(ApplicationStartedEvent event) throws Exception { - Map dataSourceMap = event.getApplicationContext().getBeansOfType(ReadableDataSource.class); - if(dataSourceMap.size() == 1) { - ReadableDataSource dataSource = dataSourceMap.values().iterator().next(); - Object ruleConfig = dataSource.loadConfig(); - SentinelProperty sentinelProperty = dataSource.getProperty(); - if(checkRuleType(ruleConfig, FlowRule.class)) { - FlowRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, DegradeRule.class)) { - DegradeRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, SystemRule.class)) { - SystemRuleManager.register2Property(sentinelProperty); - } - if(checkRuleType(ruleConfig, AuthorityRule.class)) { - AuthorityRuleManager.register2Property(sentinelProperty); - } - } - } - - private boolean checkRuleType(Object ruleConfig, Class type) { - if(ruleConfig.getClass() == type) { - return true; - } else if(ruleConfig instanceof List) { - List ruleList = (List)ruleConfig; - if(ruleList.stream().filter(rule -> rule.getClass() == type).toArray().length == ruleList.size()) { - return true; - } - } - return false; - } - - 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; - } - } - -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java deleted file mode 100644 index 09b39bb44..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.apollo.ApolloDataSource; - -/** - * @author fangjian - * @see ApolloDataSource - */ -public class ApolloDataSourceFactoryBean implements FactoryBean { - - private String namespaceName; - private String flowRulesKey; - private String defaultFlowRuleValue; - private Converter converter; - - @Override - public ApolloDataSource getObject() throws Exception { - return new ApolloDataSource(namespaceName, flowRulesKey, defaultFlowRuleValue, - converter); - } - - @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 Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java deleted file mode 100644 index 759827647..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/FileRefreshableDataSourceFactoryBean.java +++ /dev/null @@ -1,74 +0,0 @@ -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.Converter; -import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource; - -/** - * @author fangjian - * @see FileRefreshableDataSource - */ -public class FileRefreshableDataSourceFactoryBean - implements FactoryBean { - - private String file; - private String charset; - private long recommendRefreshMs; - private int bufSize; - private Converter converter; - - @Override - public FileRefreshableDataSource getObject() throws Exception { - return new FileRefreshableDataSource(new File(file), converter, - 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 Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java deleted file mode 100644 index 3de75fad4..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.springframework.cloud.alibaba.sentinel.datasource.factorybean; - -import org.springframework.beans.factory.FactoryBean; - -import com.alibaba.csp.sentinel.datasource.Converter; -import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource; - -/** - * @author fangjian - * @see NacosDataSource - */ -public class NacosDataSourceFactoryBean implements FactoryBean { - - private String serverAddr; - private String groupId; - private String dataId; - private Converter converter; - - @Override - public NacosDataSource getObject() throws Exception { - return new NacosDataSource(serverAddr, groupId, dataId, converter); - } - - @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 Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java deleted file mode 100644 index aa10270a7..000000000 --- a/spring-cloud-alibaba-sentinel/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java +++ /dev/null @@ -1,80 +0,0 @@ -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.Converter; -import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; - -/** - * @author fangjian - * @see ZookeeperDataSource - */ -public class ZookeeperDataSourceFactoryBean implements FactoryBean { - - private String serverAddr; - - private String path; - - private String groupId; - private String dataId; - - private Converter converter; - - @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, converter); - } - else { - // using path directly - return new ZookeeperDataSource(serverAddr, path, converter); - } - } - - @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 Converter getConverter() { - return converter; - } - - public void setConverter(Converter Converter) { - this.converter = Converter; - } -} diff --git a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml index 32aab630f..a2adef837 100644 --- a/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml +++ b/spring-cloud-starter-alibaba/spring-cloud-starter-alibaba-sentinel/pom.xml @@ -15,18 +15,6 @@ org.springframework.cloud spring-cloud-alibaba-sentinel - - com.alibaba.csp - sentinel-datasource-nacos - - - com.alibaba.csp - sentinel-datasource-zookeeper - - - com.alibaba.csp - sentinel-datasource-apollo -