dbcp数据库连接池工作原理--源码系列

准备

pom.xml

1
2
3
4
5
6
xml复制代码<!-- dbcp连接池-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码public class DbcpUtil {
private static DataSource dataSource = null;
//静态代码块初始化数据库连接池
static {
//通过配置文件dbcp.properties 加载dbcp相关配置文件
PropertiesUtil.load("dbcp.properties");
try {
//一个数据源 一个应用范围内加载一次
dataSource = BasicDataSourceFactory.createDataSource(PropertiesUtil.getProperties());
} catch (Exception e) {
e.printStackTrace();
}
}

//直接从连接池获取连接
public static Connection getConnection() {
Connection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ini复制代码public static void main(String[] args) {
//获取连接
Connection connection = DbcpUtil.getConnection();

String sql1 = " select * from t_user tu where name = '张三'";
Statement statement = null;
try {
statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql1);
//第四步:获取结果
while (resultSet.next()) {
String name = resultSet.getString("name");
Integer age = resultSet.getInt("age");
System.out.println("name:" + name + " age:" + age); //打印输出结果集
}
} catch (SQLException e) {
e.printStackTrace();
}

}

到这里我们就能简单的跑一个dbcp数据库连接池的demo了

源码级原理

核心类

BasicDataSourceFactory类

BasicDataSource的工厂类,创建BasicDataSource对象,此类能查看所有数据库连接池的配置

BasicDataSource类

1、主要通过public Connection getConnection() throws SQLException方法对外提供数据库连接

2、步骤1中的getConnection()是通过内部持有的DataSource 对象提供的。后面会提到是PoolingDataSource的实例。

3、通过protected synchronized DataSource createDataSource()经过一系列处理 得到PoolingDataSource的实例

PoolingDataSource类

PoolingDataSource类持有连接池ObjectPool对象,并且通过连接池对外提供getConnection()方法。

GenericObjectPool类

上面PoolingDataSource的连接池对象,提供核心方法

1
2
3
4
5
6
7
8
9
10
11
java复制代码//获取连接
Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException;

//返回连接
void returnObject(Object obj) throws Exception;

//校验连接
void invalidateObject(Object obj) throws Exception;

//添加连接
void addObject() throws Exception, IllegalStateException, UnsupportedOperationException;

PoolableConnectionFactory类

上面GenericObjectPool类的工厂类
核心方法

1
2
3
4
5
6
7
8
9
10
java复制代码//为数据库连接池提供一个连接对象
Object makeObject() throws Exception;
//为数据库连接池销毁一个连接对象
void destroyObject(Object obj) throws Exception;
//数据库连接池校验连接是否可用
boolean validateObject(Object obj);
//激活连接能够为连接池所用
void activateObject(Object obj) throws Exception;
//从连接池返回空闲状态
void passivateObject(Object obj) throws Exception;

核心流程

初始化过程

  1. 入口 加载配置 创建BasicDataSource 数据源
1
ini复制代码BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(PropertiesUtil.getProperties());

这里是通过BasicDataSourceFactory工厂创建的,经过这一步的BasicDataSource实例并没有与数据库有交互,只是简单处理了一下配置项。

注意:如果需要查看dbcp支持哪些配置,这个BasicDataSourceFactory能看到每个配置项。

  1. BasicDataSource数据源赋予能力(主要是注入的datasource的能力)

image.png
展开看整个流程 忽略上面的对象不为空直接返回
image.png

2.1、加载驱动并且返回 DriverConnectionFactory 对象,该对象具有物理创建数据库连接Connection的能力
image.png
2.2、创建一个连接池 默认是GenericObjectPool类的实例 set各种properpties

image.png

2.3、创建一个PoolableConnectionFactory 并且把它注入上面连接池,为上面连接池提供make,destory数据库连接的能力

2.4、创建真实的数据源PoolingDataSource 的对象,并且PoolingDataSource持有GenericObjectPool数据库连接池对象。GenericObjectPool对象对外核心的从连接池获取,释放连接的能力。

获取连接过程

经过了上面整个初始化,现在dbcp连接池具有了对外提供数据库连接的能力。

1
2
3
js复制代码BasicDataSource.getConnection()
-->PoolingDataSource.getConnection()
---->GenericObjectPool.borrowObject()

borrowObject流程图

borrowObject.png

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%