mirror of
https://github.com/drtrang/druid-spring-boot.git
synced 2026-10-30 21:37:31 +00:00
1.1.3
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.github.trang.druid.actuate.autoconfigure;
|
||||
|
||||
import com.github.trang.druid.actuate.DruidDataSourceEndpoint;
|
||||
import com.github.trang.druid.actuate.DruidDataSourceMvcEndpoint;
|
||||
import com.github.trang.druid.actuate.DruidDataSourceEndpoint;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
package com.github.trang.druid.autoconfigure;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.github.trang.druid.autoconfigure.DruidDataSourceConfiguration.DataSourceImportSelector;
|
||||
import com.github.trang.druid.autoconfigure.datasource.DruidDataSource2;
|
||||
import com.github.trang.druid.autoconfigure.util.CharMatcher;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.bind.PropertySourcesBinder;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Druid 数据源配置
|
||||
*
|
||||
* @author trang
|
||||
*/
|
||||
@Import(DataSourceImportSelector.class)
|
||||
@Slf4j
|
||||
public class DruidDataSourceConfiguration {
|
||||
|
||||
/**
|
||||
* 单数据源注册
|
||||
*
|
||||
* @author trang
|
||||
*/
|
||||
static class SingleDataSourceRegister implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
static final String BEAN_NAME = "dataSource";
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(BEAN_NAME)) {
|
||||
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(DruidDataSource2.class)
|
||||
.setInitMethodName("init")
|
||||
.setDestroyMethodName("close")
|
||||
.getBeanDefinition();
|
||||
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
|
||||
log.debug("druid data-source init...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 多数据源注册
|
||||
*
|
||||
* @author trang
|
||||
*/
|
||||
static class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
|
||||
|
||||
private static final String BEAN_SUFFIX = "DataSource";
|
||||
private RelaxedPropertyResolver resolver;
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
resolver.getSubProperties("").keySet().stream()
|
||||
.map(key -> key.substring(0, key.indexOf(".")))
|
||||
.distinct()
|
||||
.forEach(dataSourceName -> {
|
||||
// 构造 BeanDefinition,通过 DruidDataSource2 实现继承 'spring.datasource.druid' 的配置
|
||||
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(DruidDataSource2.class)
|
||||
.setInitMethodName("init")
|
||||
.setDestroyMethodName("close")
|
||||
.getBeanDefinition();
|
||||
// 注册 BeanDefinition
|
||||
registry.registerBeanDefinition(dataSourceName, beanDefinition);
|
||||
// 注册驼峰别名
|
||||
String camelAlias = CharMatcher.separatedToCamel().apply(dataSourceName);
|
||||
registry.registerAlias(dataSourceName, camelAlias);
|
||||
// 注册以 DataSource 为后缀的别名
|
||||
String otherAlias;
|
||||
if (camelAlias.toLowerCase().endsWith(BEAN_SUFFIX.toLowerCase())) {
|
||||
if (!camelAlias.endsWith(BEAN_SUFFIX)) {
|
||||
otherAlias = camelAlias.substring(0, camelAlias.toLowerCase().indexOf(BEAN_SUFFIX.toLowerCase()));
|
||||
otherAlias = otherAlias + BEAN_SUFFIX;
|
||||
registry.registerAlias(dataSourceName, otherAlias);
|
||||
}
|
||||
} else {
|
||||
otherAlias = camelAlias + BEAN_SUFFIX;
|
||||
registry.registerAlias(dataSourceName, otherAlias);
|
||||
}
|
||||
log.debug("druid {}-data-source init...", dataSourceName);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.resolver = new RelaxedPropertyResolver(environment, "spring.datasource.druid.data-sources.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据源选择器
|
||||
* 当配置文件中存在 spring.datasource.druid.data-sources 属性时为多数据源
|
||||
* 不存在则为单数据源
|
||||
*
|
||||
* @author trang
|
||||
*/
|
||||
static class DataSourceImportSelector implements ImportSelector, EnvironmentAware {
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata metadata) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment, "spring.datasource.druid.");
|
||||
Map<String, Object> properties = resolver.getSubProperties("data-sources");
|
||||
if (properties.isEmpty()) {
|
||||
return new String[]{SingleDataSourceRegister.class.getName()};
|
||||
}
|
||||
return new String[]{DynamicDataSourceRegister.class.getName(),
|
||||
DataSourceBeanPostProcessor.class.getName()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = (ConfigurableEnvironment) environment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* DataSource Bean 处理器
|
||||
*
|
||||
* @author trang
|
||||
*/
|
||||
static class DataSourceBeanPostProcessor implements BeanPostProcessor, EnvironmentAware {
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DruidDataSource) {
|
||||
// 将 'spring.datasource.druid.data-sources.${name}' 的配置绑定到 Bean
|
||||
PropertySourcesBinder binder = new PropertySourcesBinder(environment);
|
||||
binder.bindTo("spring.datasource.druid.data-sources." + beanName, bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = (ConfigurableEnvironment) environment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package com.github.trang.druid.autoconfigure.util;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author trang
|
||||
*/
|
||||
public final class CharMatcher {
|
||||
|
||||
public static Manipulation none() {
|
||||
return Manipulation.NONE;
|
||||
}
|
||||
|
||||
public static Manipulation separatedToCamel() {
|
||||
return Manipulation.SEPARATED_TO_CAMELCASE;
|
||||
}
|
||||
|
||||
public static Manipulation camelToHyphen() {
|
||||
return Manipulation.CAMELCASE_TO_HYPHEN;
|
||||
}
|
||||
|
||||
public static enum Manipulation {
|
||||
|
||||
NONE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
HYPHEN_TO_UNDERSCORE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value.indexOf('-') != -1 ? value.replace('-', '_') : value;
|
||||
}
|
||||
},
|
||||
|
||||
UNDERSCORE_TO_PERIOD {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value.indexOf('_') != -1 ? value.replace('_', '.') : value;
|
||||
}
|
||||
},
|
||||
|
||||
PERIOD_TO_UNDERSCORE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value.indexOf('.') != -1 ? value.replace('.', '_') : value;
|
||||
}
|
||||
},
|
||||
|
||||
CAMELCASE_TO_UNDERSCORE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
if (value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
Matcher matcher = CAMEL_CASE_PATTERN.matcher(value);
|
||||
if (!matcher.find()) {
|
||||
return value;
|
||||
}
|
||||
matcher = matcher.reset();
|
||||
StringBuffer result = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(result, matcher.group(1) + '_' + StringUtils.uncapitalize(matcher.group(2)));
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
return result.toString();
|
||||
}
|
||||
},
|
||||
|
||||
CAMELCASE_TO_HYPHEN {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
if (value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
Matcher matcher = CAMEL_CASE_PATTERN.matcher(value);
|
||||
if (!matcher.find()) {
|
||||
return value;
|
||||
}
|
||||
matcher = matcher.reset();
|
||||
StringBuffer result = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(result, matcher.group(1) + '-'
|
||||
+ StringUtils.uncapitalize(matcher.group(2)));
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
return result.toString();
|
||||
}
|
||||
},
|
||||
|
||||
SEPARATED_TO_CAMELCASE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return separatedToCamelCase(value, false);
|
||||
}
|
||||
},
|
||||
|
||||
CASE_INSENSITIVE_SEPARATED_TO_CAMELCASE {
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return separatedToCamelCase(value, true);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])");
|
||||
private static final Pattern SEPARATED_TO_CAMEL_CASE_PATTERN = Pattern.compile("[_\\-.]");
|
||||
private static final char[] SUFFIXES = new char[]{'_', '-', '.'};
|
||||
|
||||
public abstract String apply(String value);
|
||||
|
||||
private static String separatedToCamelCase(String value, boolean caseInsensitive) {
|
||||
if (value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String field : SEPARATED_TO_CAMEL_CASE_PATTERN.split(value)) {
|
||||
field = (caseInsensitive ? field.toLowerCase() : field);
|
||||
builder.append(builder.length() == 0 ? field : StringUtils.capitalize(field));
|
||||
}
|
||||
char lastChar = value.charAt(value.length() - 1);
|
||||
for (char suffix : SUFFIXES) {
|
||||
if (lastChar == suffix) {
|
||||
builder.append(suffix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user