目录
上一篇文章介绍了druid-spring-boot-starter是如何一步步调用到DruidDataSource的init()方法的,那么今天主要就来分析看看init是如何初始化的。
1 初始化整体流程
DruidDataSource.init()方法整体流程可以概括为以下步骤:
- 判断是否已初始化
- 加锁处理
- 初始化id、jdbcUrl、dbTypeName、dbType、filter等
- 校验maxActive、minIdle、timeBetweenLogStatsMillis、useGlobalDataSourceStat、maxEvictableIdleTimeMillis、minEvictableIdleTimeMillis、keepAlive、driverClass等
- load filters from SPI ServiceLoader
- 初始化driver
- 初始化ExceptionSorter、ValidConnectionChecker、JdbcDataSourceStat
- 初始化maxActive数量的连接
- 创建logStatsThread、createConnectionThread和destroyConnectionThread
- 注册MBean,用于支持JMX
- 如果设置了keepAlive,通知createConnectionThread创建连接对象
- 解锁
- 打印初始化完成
2、初始化具体流程分析
2.1 判断是否已初始化
init方法一进来就会判断是否已初始化,如果检测到已初始化,则直接返回。
2.2 加锁处理
druid数据源初始化采用的是ReentrantLock,从以上截图源码部分可以看到会通过lock.lockInterruptibly()进行加锁处理,该方法和lock.lock()的区别在于这个方法一旦产生中断就会直接抛出异常交给上层处理。
2.3 初始化id、jdbcUrl、dbTypeName、dbType、filter等
加锁之后,会再次判断是否已初始化,值得借鉴,新手一般容易忽视。这段代码里会初始化id、jdbcUrl、dbTypeName、dbType、filter等
其中获取dbType的时候会通过前缀进行判断,如上代码截图所示。
2.4 校验maxActive、minIdle、timeBetweenLogStatsMillis、useGlobalDataSourceStat、maxEvictableIdleTimeMillis、minEvictableIdleTimeMillis、keepAlive、driverClass等
从以上截图可以获知是一些相关的druid的配置做一些校验。
2.5 load filters from SPI ServiceLoader
初始化到这一步,有一个通过SPI方式初始化添加AutoLoad注解的过滤器。
2.6 初始化driver
这一段的核心逻辑就是会根据url去判断是属于什么驱动,然后去初始化一个对应数据库的驱动。
2.7 初始化ExceptionSorter、ValidConnectionChecker、JdbcDataSourceStat
判断driverClass,初始化一个对应数据库驱动的exceptionSorter。
判断driverClass,初始化一个对应数据库驱动的validConnectionChecker,同时会进行尝试连接测试。
校验是否符合QueryCheck条件。
2.8 初始化maxActive数量的连接
核心逻辑来了,首先会先创建一个maxActive数量的DruidConnectionHolder的数组,
Druid可以认为是conn以及dataSource的包装类,数组创建成功后则会开始连接数据库创建真正的连接缓存到数组中。
以上会连接数据库创建连接的过程,并且会通过一个ConnectionProxyImpl代理Connection,最终循环创建成功所有的连接对象。
2.9 创建logStatsThread、createConnectionThread和destroyConnectionThread
这里标记下重点,这三个方法调用,特别是后面两个是大核心。这里先做下简单介绍:
- createAndLogThread()启动监控数据记录线程
- createAndStartCreatorThread()启动创建线程
- createAndStartDestroyThread()启动检测线程销毁处理
2.10 注册MBean,用于支持JMX
用于支持JMX
2.11 如果设置了keepAlive,通知createConnectionThread创建连接对象
通知createConnectionThread创建连接对象
2.12 解锁
lock.unlock();
2.13 打印初始化完成
打印初始化完成