matrix.boot.jdbc.config.DataSourceAutoConfiguration Maven / Gradle / Ivy
The newest version!
package matrix.boot.jdbc.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import matrix.boot.common.utils.AssertUtil;
import matrix.boot.common.utils.StringUtil;
import matrix.boot.jdbc.beans.DynamicDataSource;
import matrix.boot.jdbc.beans.MoreDataSource;
import matrix.boot.jdbc.enums.DataSourceType;
import matrix.boot.jdbc.metadata.DruidDataSourcePoolMetadata;
import matrix.boot.jdbc.properties.JdbcProperties;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceUnwrapper;
import org.springframework.boot.jdbc.metadata.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.CollectionUtils;
import javax.sql.DataSource;
import java.util.*;
/**
* 数据库自动装配
* @author wangcheng
* date 2021/8/15
*/
@EnableConfigurationProperties(JdbcProperties.class)
@ConditionalOnProperty(value = {"matrix.jdbc.enabled"})
@EnableTransactionManagement
@Slf4j
public class DataSourceAutoConfiguration {
/**
* jdbc配置
*/
private final JdbcProperties jdbcProperties;
public DataSourceAutoConfiguration(JdbcProperties jdbcProperties) {
this.jdbcProperties = jdbcProperties;
}
/**
* 数据库源信息提供者
* @return 数据库源信息提供者
*/
@Bean
public DataSourcePoolMetadataProvider dataSourcePoolMetadataProvider() {
return this::getDataSourcePoolMetadata;
}
/**
* 多数据源集合
*
* @return 多数据源
*/
@Bean
@Primary
public MoreDataSource moreDataSource() {
//数据库创建集合
Map dbMap = new LinkedHashMap<>();
//加入数据库集合
if (!CollectionUtils.isEmpty(jdbcProperties.getDbList())) {
jdbcProperties.getDbList().forEach((key, db) -> {
if (db.isEnabled()) {
dbMap.put(key, db);
}
});
}
//定义数据源集合
LinkedHashMap dataSourceMap = new LinkedHashMap<>();
//获取数据源类型
DataSourceType dataSourceType = DataSourceType.getByCode(jdbcProperties.getDataSourceType());
if (DataSourceType.DRUID.equals(dataSourceType)) {
//德鲁伊数据源
dbMap.forEach((key, db) -> dataSourceMap.put(key, buildDruidDataSource(jdbcProperties, db)));
} else if (DataSourceType.Hikari.equals(dataSourceType)) {
//Hikari数据源
dbMap.forEach((key, db) -> dataSourceMap.put(key, buildHikariDataSource(jdbcProperties, db)));
}
log.info("MoreDataSource init success!");
return new MoreDataSource(dataSourceMap);
}
/**
* 构建德鲁伊数据连接池
*
* @param jdbcProperties jdbc参数
* @param dbInfo 数据库参数
* @return 德鲁伊数据源
*/
private DruidDataSource buildDruidDataSource(JdbcProperties jdbcProperties, JdbcProperties.DB dbInfo) {
//校验参数
validateDBInfo(dbInfo);
//创建德鲁伊数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(dbInfo.getDriverClass());
dataSource.setUrl(dbInfo.getUrl());
dataSource.setUsername(dbInfo.getUsername());
if (!StringUtil.isEmpty(dbInfo.getPassword())) {
dataSource.setPassword(dbInfo.getPassword());
}
//打开PSCache,并且指定每个连接上PSCache的大小
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
//通过connectProperties属性来打开mergeSql功能
dataSource.setConnectionProperties("druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000");
//合并多个DruidDataSource的监控数据
dataSource.setUseGlobalDataSourceStat(true);
dataSource.setMinEvictableIdleTimeMillis(300000);
dataSource.setValidationQuery(dbInfo.getTestQuery());
dataSource.setTestWhileIdle(false);
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setTimeBetweenEvictionRunsMillis(60000);
dataSource.setMaxWait(60000);
//最大激活数
dataSource.setMaxActive(jdbcProperties.getMaxActivePoolSize());
//最小空闲数
dataSource.setMinIdle(jdbcProperties.getMinIdlePoolSize());
//初始化连接数
dataSource.setInitialSize(jdbcProperties.getInitialPoolSize());
dataSource.setAsyncInit(true);
try {
dataSource.setFilters("stat");
} catch (Exception e) {
log.debug(e.getMessage(), e);
}
return dataSource;
}
/**
* 构建Hikari数据连接池
* @param jdbcProperties jdbc参数
* @param dbInfo 数据库参数
* @return Hikari数据源
*/
private HikariDataSource buildHikariDataSource(JdbcProperties jdbcProperties, JdbcProperties.DB dbInfo) {
//实例化类
HikariConfig hikariConfig = new HikariConfig();
//设置驱动
hikariConfig.setDriverClassName(dbInfo.getDriverClass());
//设置url
hikariConfig.setJdbcUrl(dbInfo.getUrl());
//数据库帐号
hikariConfig.setUsername(dbInfo.getUsername());
//数据库密码
if (!StringUtil.isEmpty(dbInfo.getPassword())) {
hikariConfig.setPassword(dbInfo.getPassword());
}
//最小空闲数
hikariConfig.setMinimumIdle(jdbcProperties.getMinIdlePoolSize());
//最大连接数
hikariConfig.setMaximumPoolSize(jdbcProperties.getMaxActivePoolSize());
hikariConfig.setConnectionTestQuery(dbInfo.getTestQuery());
hikariConfig.addDataSourceProperty("cachePrepStmts", "true");
hikariConfig.addDataSourceProperty("prepStmtCacheSize", "250");
hikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
return new HikariDataSource(hikariConfig);
}
/**
* 校验DB信息
* @param dbInfo db信息
*/
private void validateDBInfo(JdbcProperties.DB dbInfo) {
AssertUtil.notNullTip(dbInfo.getDriverClass(), "jdbc db driverClass can not be null");
AssertUtil.notNullTip(dbInfo.getUrl(), "jdbc db url can not be null");
AssertUtil.notNullTip(dbInfo.getUsername(), "jdbc db username can not be null");
AssertUtil.notNullTip(dbInfo.getPassword(), "jdbc db password can not be null");
}
/**
* 排除自动装配过滤器
*/
public static class ExcludeAutoConfigurationFilter implements AutoConfigurationImportFilter {
private static final Set SHOULD_SKIP = new HashSet<>(Arrays.asList(
"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration",
"org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration"));
@Override
public boolean[] match(String[] classNames, AutoConfigurationMetadata metadata) {
boolean[] matches = new boolean[classNames.length];
for (int i = 0; i < classNames.length; i++) {
matches[i] = !SHOULD_SKIP.contains(classNames[i]);
}
return matches;
}
}
/**
* 获取数据源链接元信息
* @return 数据源链接元信息
*/
private DataSourcePoolMetadata getDataSourcePoolMetadata(DataSource dataSource) {
if (dataSource == null) {
return null;
}
if (dataSource instanceof HikariDataSource) {
return new HikariDataSourcePoolMetadata(DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class));
} else if (dataSource instanceof DruidDataSource) {
return new DruidDataSourcePoolMetadata(DataSourceUnwrapper.unwrap(dataSource, DruidDataSource.class));
} else if (dataSource instanceof DynamicDataSource) {
return getDataSourcePoolMetadata(((DynamicDataSource) dataSource).getResolvedDefaultDataSource());
} else if (dataSource instanceof ShardingDataSource) {
Map dataSourceMap = ((ShardingDataSource) dataSource).getDataSourceMap();
return getDataSourcePoolMetadata(dataSourceMap.values().iterator().next());
}
return null;
}
}