druid1.2.8源码阅读:第三天
文章目录
- druid1.2.8源码阅读:第三天
- 一、创建连接
- 1.1 `init()`方法
- (1)`JdbcUtils.getDbType`
- (2)根据DbType设置`cacheServerConfiguration`
- (4)校验参数设置的是否正确
- (5)`initFromSPIServiceLoader()`
- (6)`resolveDriver();` 加载数据库驱动
- (7)`initCheck();`确实使用的是什么数据库
- (8)`initExceptionSorter();`
- (9)`initValidConnectionChecker();`
- (10)`validationQueryCheck();` 打印了几条配置参数的日志
- (11)创建`JdbcDataSourceStat`
- (12)数据库连接池中连接的转换数组定义
- (13)当initialSize 大于0时,初始化连接
- (14)`createAndLogThread();`
- (15)`createAndStartCreatorThread();`
- (16)`createAndStartDestroyThread()`
- (18)`registerMbean();`调用C++的方法
一、创建连接
Connection connection = dataSource.getConnection();
在druid中,实际获取的是DruidPooledConnection。
1.1 init()方法
如果连接池已经初始化了,直接返回:
if (inited) {
return;
}
加载数据库驱动:
根据传入的url判断,去加载哪种数据库驱动。
(1)JdbcUtils.getDbType
根据URL的前缀获取数据类型:比如DbType.mysql,“mysql”
if (this.dbTypeName == null || this.dbTypeName.length() == 0) {
this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);
}
(2)根据DbType设置cacheServerConfiguration
对于部分数据库,可以设置这个配置
if (dbType == DbType.mysql
|| dbType == DbType.mariadb
|| dbType == DbType.oceanbase
|| dbType == DbType.ads) {
boolean cacheServerConfigurationSet = false;
if (this.connectProperties.containsKey("cacheServerConfiguration")) {
cacheServerConfigurationSet = true;
} else if (this.jdbcUrl.indexOf("cacheServerConfiguration") != -1) {
cacheServerConfigurationSet = true;
}
if (cacheServerConfigurationSet) {
this.connectProperties.put("cacheServerConfiguration", "true");
}
}
(4)校验参数设置的是否正确
maxActive 连接池中最多支持多少个活动会话
- maxActive必须大于0
- maxActive不能小于minIdle的数值。(minIdle,回收空闲连接时,将保证至少有minIdle个连接)
- maxActive 的值必须大于或等于
initialSize的大小。(initialSize,启动程序时,在连接池中初始化多少个连接)
useGlobalDataSourceStat 为true的时候,timeBetweenLogStatsMillis 值不能大于0
- useGlobalDataSourceStat :合并多个数据源的监控数据
- timeBetweenLogStatsMillis :间隔多久将统计信息输出到日志
maxEvictableIdleTimeMillis 的值,不能小于minEvictableIdleTimeMillis的值
maxEvictableIdleTimeMillis:当连接池中只剩下最少连接数的时候(minIdle),这些线程空闲多久关闭。默认7小时。minEvictableIdleTimeMillis:非最小连接数的空闲连接,被逐出数据库连接池的最小时间。
keepAlive 为true的时候,keepAliveBetweenTimeMillis的值必须大于timeBetweenEvictionRunsMillis
- keepAlive 是否维护空闲连接有效
- keepAliveBetweenTimeMillis 空闲连接空闲的开始时候,启动保活机制
- timeBetweenEvictionRunsMillis 启动销毁空闲连接的时间周期
(5)initFromSPIServiceLoader()
如果loadSpifilterSkip 为true,就从再通过SPI加载过滤器。
(6)resolveDriver(); 加载数据库驱动
-
如果
driverClass参数为空,则根据jdbcUrl获取driverClass;获取的driverClass值就为com.mysql.cj.jdbc.Driver
this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);-
如果jdbcUrl的前缀为
jdbc:mysql:那么加载数据库驱动包mysql_driver_version_6 = Utils.loadClass("com.mysql.cj.jdbc.Driver") != null; // 内部: Class.forName(className);
-
-
根据
dirverClass创建驱动DriverClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); Class<?> clazz = contextLoader.loadClass(driverClassName); Driver driver = (Driver) clazz.getDeclaredConstructor().newInstance();
Class.forName(className);
Class<?> clazz = contextLoader.loadClass(driverClassName);
Driver driver = (Driver) clazz.getDeclaredConstructor().newInstance();
(7)initCheck();确实使用的是什么数据库
根据DbType设置类型:
isMySql = true;
(8)initExceptionSorter();
- 如果exceptionSorter 是
NullExceptionSorter类型,并且驱动是MockDriver类型,直接返回 - 或者如果exceptionSorter 不为空,就返回
否则,根据真实的realDriverClassName值(比如:com.mysql.cj.jdbc.Driver)
this.exceptionSorter = new MySqlExceptionSorter();
(9)initValidConnectionChecker();
如果validConnectionChecker不为空,就返回。
否则,根据真实的realDriverClassName值(比如:com.mysql.cj.jdbc.Driver)
this.validConnectionChecker = new MySqlValidConnectionChecker();
// clazz = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
(10)validationQueryCheck(); 打印了几条配置参数的日志
如果 validConnectionChecker 不为空,就返回;
(11)创建JdbcDataSourceStat
(12)数据库连接池中连接的转换数组定义
connections = new DruidConnectionHolder[maxActive];
//准备关闭的
evictConnections = new DruidConnectionHolder[maxActive];
//
keepAliveConnections = new DruidConnectionHolder[maxActive];
(13)当initialSize 大于0时,初始化连接
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
connections[poolingCount++] = holder;
(14)createAndLogThread();
只有当timeBetweenLogStatsMillis的值大于0的时候,才会创建日志状态线程。
(15)createAndStartCreatorThread();
createConnectionThread = new CreateConnectionThread(threadName);
createConnectionThread.start();
// initedLatch.countDown();
(16)createAndStartDestroyThread()
destroyConnectionThread = new DestroyConnectionThread(threadName);
destroyConnectionThread.start();
####(17)initedLatch.await();等待15、16步执行完
(18)registerMbean();调用C++的方法
AccessController.doPrivileged
3065



被折叠的 条评论
为什么被折叠?



