Druid源码分析(五)-- 连接池
Druid源码分析(五)-- 连接池
连接池
我们可以看到 druid-spring-boot-starter 的配置是初始化连接2个,连接池最大数量是30,最小数量是2个
# Druid 数据源配置,继承spring.datasource.* 配置,相同则覆盖
spring.datasource.druid.initial-size=2
spring.datasource.druid.max-active=30
spring.datasource.druid.min-idle=2
然后这边默认是同步初始化
private boolean asyncInit = false;
当然我们可以在配置文件加上这行配置,改为异步初始化
spring.datasource.druid.async-init=true
前面 init 函数里有一段代码,同步初始化的时候,会循环创建配置的初始化数量的连接
while (poolingCount < initialSize) {
try {
// 创建连接
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
// 把连接包装成DruidConnectionHolder
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
// 把连接加入连接池
connections[poolingCount++] = holder;
} catch (SQLException ex) {
...
}
}
debug可以看到,配置是没问题的,然后这边会循环2次创建连接conn,加入到连接池
我们接着往里看,这边是先创建物理数据库连接,然后再包装成DruidConnectionHolder ,加入到连接池
// DruidAbstractDataSource.java
public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
...
conn = createPhysicalConnection(url, physicalConnectProperties);
这里又调用了另一个函数来创建连接
// DruidAbstractDataSource.java
public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
Object conn;
// 这里判断有没有filter,如果没有,直接通过驱动创建连接,有的话,需要通过责任链的形式创建连接
if (this.getProxyFilters().size() == 0) {
conn = this.getDriver().connect(url, info);
} else {
conn = (new FilterChainImpl(this)).connection_connect(info);
}
createCountUpdater.incrementAndGet(this);
return (Connection)conn;
}
因为我们这边配置开启了statFilter,所以走的是下面的责任链模式创建连接
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
不过里面最终还是用数据库驱动去获取的连接conn
// FilterChainImpl.java
public ConnectionProxy connection_connect(Properties info) throws SQLException {
if (this.pos < this.filterSize) {
// 责任链模式循环filter
return this.nextFilter().connection_connect(this, info);
} else {
Driver driver = this.dataSource.getRawDriver();
String url = this.dataSource.getRawJdbcUrl();
// 通过驱动获取连接
Connection nativeConnection = driver.connect(url, info);
return nativeConnection == null ? null : new ConnectionProxyImpl(this.dataSource, nativeConnection, info, this.dataSource.createConnectionId());
}
}
创建物理数据库连接后,就是把连接包装成DruidConnectionHolder ,设置数据源、连接、连接创建时间、连接时间、是否自动提交等
// DruidConnectionHolder.java
this.dataSource = dataSource;
this.conn = conn;
this.createNanoSpan = connectNanoSpan;
this.connectTimeMillis = System.currentTimeMillis();
this.lastActiveTimeMillis = connectTimeMillis;
this.lastExecTimeMillis = connectTimeMillis;
this.underlyingAutoCommit = conn.getAutoCommit();
...
最后连接池里就有了2个连接
总结
Druid连接池里存的是包装过后扩展了很多参数的连接conn ,这些连接最终还是通过数据库驱动来创建的,然后这边的filter用到了责任链模式,和shenyu项目是很像的,如果我们写项目,支持用户自定义filter,也可以用责任链模式。