一.问题背景:
最近在做一些并发测试,在调试数据库连接数时发现参数怎么调整都没变化,感觉可能是参数有问题,并没有生效,但是数据库url、用户名密码登关键信息是对的(不然连不上数据库),通过Debug也证实以上信息是正确的,但是像初始连接数、最大连接数、最小空闲数这些都没有生效,我的配置如下
于是为了搞清楚原因,Debug搞起,看看Druid数据源是怎么初始化的。
由于我们的SpringBoot项目并没有配置任何关于数据源初始化的代码,所以一定是SpringBoot自动装配起的作用,自动装配一定要创建DruidDataSource这个类,于是在这个类上打上端点看调用链。
果然,断点生效了,然后再看调用链
找到了配置的入口地方
这个类的上边有一个DataSourceAutoConfiguration,就是它了,自动装配
果然,这里面又配置了Generic类
参数配置中还必须有这个参数spring.datasource.type,而且这个类型也决定了使用哪种数据源,再看我们的参数配置,也确实有这个配置spring.datasource.type=com.alibaba.druid.pool.DruidDataSource(把这个去掉启动就会报错,无法初始化数据源),搞清楚了源头我们继续跟进入参properties,发现了spring.datasource这个前缀,跟我们的配置中心是匹配的,但是像maxActive这些参数在这个类中是没有的
这也就明白了为啥配置不生效,参数写错了,druid并不认识
从DruidDataSource构造方法继续跟进发现Druid数据源有自己的参数前缀
但是此处的前缀是系统级参数,并不是配置文件中的参数,所以在配置中心中设置的参数除了地址、用户密码等其他参数全部无效。
二.解决方案
方案一: 利用Bean后置处理器手动处理无效的参数
@Component
public class DruidDataSourceInit implements BeanPostProcessor {
@Resource
private Environment env;
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, @Nullable String beanName) throws BeansException {
if(bean instanceof DruidDataSource){
DruidDataSource druidDataSource = (DruidDataSource)bean;
String initialSize = env.getProperty("spring.datasource.initialSize");
String maxActive = env.getProperty("spring.datasource.maxActive");
String minIdle = env.getProperty("spring.datasource.minIdle");
String maxWait = env.getProperty("spring.datasource.maxWait");
String filters = env.getProperty("spring.datasource.filters");
if(!StringUtils.isEmpty(initialSize)){
druidDataSource.setInitialSize(Integer.parseInt(initialSize));
}
if(!StringUtils.isEmpty(maxActive)){
druidDataSource.setMaxActive(Integer.parseInt(maxActive));
}
if(!StringUtils.isEmpty(minIdle)){
druidDataSource.setMinIdle(Integer.parseInt(minIdle));
}
if(!StringUtils.isEmpty(maxWait)){
druidDataSource.setMaxWait(Integer.parseInt(maxWait));
}
if(!StringUtils.isEmpty(filters)){
try {
druidDataSource.setFilters(filters);
} catch (SQLException e) {
}
}
}
return bean;
}
}
方案二: 引入druid-spring-boot-starter自动装配
前提是需要将Springboot默认的数据源自动配置类排除,启动类上添加如下注释
@SpringBootApplication(exclude ={DataSourceAutoConfiguration.class} )
此时配置文件中的参数需要改为类似spring.datasource.druid.maxActive,源码如下: