1、init过程
在getConnection获取连接时最开始执行init()方法,执行初始化操作
public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
// 在初始化dataSource时并不会执行init,而是在第一次获取连接的时候进行init
init();
if (filters.size() > 0) {
FilterChainImpl filterChain = new FilterChainImpl(this);
return filterChain.dataSource_connect(this, maxWaitMillis);
} else {
return getConnectionDirect(maxWaitMillis);
}
}
init采用Double Check机制防止重复执行,因为在线程释放锁的时候,初始化过程可能还未完成 ;
线程上锁lock.lockInterruptibly()
public void init() throws SQLException {
if (inited) {
return;
}
// bug fixed for dead lock, for issue #2980
DruidDriver.getInstance();
final ReentrantLock lock = this.lock;
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
throw new SQLException("interrupt", e);
}
boolean init = false;
try {
// DCL
if (inited) {
return;
}
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());
// 分配数据源id{dataSource-id}
this.id = DruidDriver.createDataSourceId();
if (this.id > 1) {
long delta = (this.id - 1) * 100000;
this.connectionIdSeedUpdater.addAndGet(this, delta);
this.statementIdSeedUpdater.addAndGet(this, delta);
this.resultSetIdSeedUpdater.addAndGet(this, delta);
this.transactionIdSeedUpdater.addAndGet(this, delta);
}
if (this.jdbcUrl != null) {
this.jdbcUrl = this.jdbcUrl.trim();
// 如果jdbcUrl 以jdbc:wrap-jdbc,那么启动代理
initFromWrapDriverUrl();
}
// 遍历所有配置的filter,并且执行它们的init方法
for (Filter filter : filters) {
filter.init(this);
}
// 根据jdbcUrl来判断是哪种数据源
if (this.dbTypeName == null || this.dbTypeName.length() == 0) {
this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);
}
。。。
// SPI 方式创建filter对象
initFromSPIServiceLoader();
// 根据配置的driver,配置驱动
resolveDriver();
// 对一些数据源进行特殊检查
initCheck();
// 根据不同的数据源分配不同的异常处理器
initExceptionSorter();
initValidConnectionChecker();
validationQueryCheck