使用Druid进行连接数据库报错,实在不知道问题出在哪里,报错信息在第53行conn = ds.getConnection();
ds为空。
先不要调接口,看看程序初始化启动时DBManager类打印了什么错误
看这个地方报错信息是什么
这里是Druid的三个核心线程的交互逻辑图
⚠️这里是init();初始化在这一步:主要核心就是创建这几个线程
createAndLogThread(); //打印日志线程其实就是统计监控信息
createAndStartCreatorThread(); //创建连接的线程
createAndStartDestroyThread(); //销毁连接的线程
首先第一大步骤就是先去获取DruidPooledConnection,通过getConnectionInternal()方法
进入到方法内:
PhysicalConnectionInfo pyConnInfo = DruidDataSource.this.createPhysicalConnection();
holder = new DruidConnectionHolder(this, pyConnInfo);
JdbcUtils.close(pyConnInfo.getPhysicalConnection());
如果成功继续走到下一步
如果失败捕获住错误的话,就继续尝试获取DruidPooledConnection
然后回到getConnectionDirect()方法中,走到第二个步骤中,先判断配置参数testOnBorrow是不是为True,然后去进行对连接进行校验,如果校验成功就继续往下走,
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
Connection realConnection = poolableConnection.conn;
discardConnection(realConnection);
continue;
}
如果配置参数testOnBorrow为True的话会先进行一次上面代码的校验,如果testOnBorrow为False的话,并且 testWhileIdle参数为True的话,会再进行判断,如果【timeBetweenEvictionRunsMillis <= 0】直接使用 60s 进行填充
继续走,如果当前连接的空闲时间【idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0】时,会继续进行校验当前连接的健康情况,和上面代码一样,如果校验不成功就会discard当前的Connection
继续,然后判断配置参数removeAbandoned是不是为True,如果是就以当前连接poolableConnection 为Key,PRESENT作为Value放到activeConnections的Map集合中
Map<DruidPooledConnection, Object> activeConnections = new IdentityHashMap<DruidPooledConnection, Object>();
//这里是判断逻辑
if (removeAbandoned) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.connectStackTrace = stackTrace;
poolableConnection.setConnectedTimeNano();
poolableConnection.traceEnable = true;
activeConnectionLock.lock();
try {
activeConnections.put(poolableConnection, PRESENT);
} finally {
activeConnectionLock.unlock();
}
}
⚠️这里补充一下第一大步的第2小步中的pollLast(nanos)和takeLast(nanos)方法中如果没有从LRU队列中的尾部获取到Connection时,就会发送图中的notify信号,去通知创建连接的线程去创建连接**