原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處定枷。
簡(jiǎn)單總結(jié)DruidDataSource初始化過(guò)程
- 讀取配置文件届氢,創(chuàng)建并配置DruidDataSource
- 注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)DruidDriver
- 開(kāi)始初始化,加鎖
- 同步或者異步初始化DruidDataSource退子,主要是創(chuàng)建initialSize個(gè)連接放入空閑連接池
- 創(chuàng)建、運(yùn)行連接池狀態(tài)統(tǒng)計(jì)日志線(xiàn)程衣吠、連接創(chuàng)建線(xiàn)程壤靶、連接銷(xiāo)毀線(xiàn)程
- 初始化完畢惊搏,釋放鎖
核心流程其實(shí)很簡(jiǎn)單,主要的復(fù)雜邏輯集中在線(xiàn)程之間的交互上恬惯。如果看過(guò)MyBatis的簡(jiǎn)單連接池實(shí)現(xiàn)的話(huà),可以說(shuō)Druid的核心實(shí)現(xiàn)就是在MyBatis基礎(chǔ)上增加了獨(dú)立的創(chuàng)建浓恳、銷(xiāo)毀連接線(xiàn)程,增加了日志和監(jiān)控颈将,使這個(gè)初始化過(guò)程變得復(fù)雜了。
DruidDataSource初始化準(zhǔn)備工作--before init()
- 讀取晴圾、解析配置文件,封裝為Map
- 使用工廠方法DruidDataSourceFactory.createDataSource(Map properties)創(chuàng)建一個(gè)DruidDataSource人乓。
- 初始化非公平ReentrantLock都毒,和生產(chǎn)者、消費(fèi)者監(jiān)視器
- 使用傳入的map來(lái)配置DruidDataSource
- DruidDataSource對(duì)象的初始化账劲。有兩個(gè)地方可以觸發(fā)初始化動(dòng)作:
- 可以在配置中指定 init=true,會(huì)在set配置值時(shí)調(diào)用dataSource.init()姑尺,完成初始化蝠猬。
- 在調(diào)用dataSource.getConnection(long maxWaitMillis)時(shí),會(huì)調(diào)用dataSource.init()榆芦,完成初始化。
DruidDataSource初始化開(kāi)始--do init()
- 禁止重復(fù)初始化
- 注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)DruidDriver
- lock.lockInterruptibly();
- 分配唯一dataSourceId
- 如果有過(guò)濾器Filter驻右,使用過(guò)濾器鏈包裝dataSource
- SPI加載擴(kuò)展服務(wù)
- 初始化空閑連接池崎淳、待刪除連接池、奔鸢迹活連接池
- 判斷走異步初始化、還是同步初始化爬迟,一般為同步初始化
- 根據(jù)配置的initialSize數(shù)量菊匿,創(chuàng)建數(shù)據(jù)庫(kù)連接代理计福,放入空閑連接池
- 啟動(dòng)連接池狀態(tài)統(tǒng)計(jì)日志線(xiàn)程徽职、連接創(chuàng)建線(xiàn)程棒搜、連接銷(xiāo)毀線(xiàn)程
- 主線(xiàn)程阻塞在CountDownLatch(2)活箕,等待連接創(chuàng)建線(xiàn)程、連接銷(xiāo)毀線(xiàn)程運(yùn)行起來(lái)克蚂。
- 向JMX注冊(cè)線(xiàn)程池監(jiān)控MBean
- 如果配置了苯钐郑活keepAlive,喚醒生產(chǎn)者線(xiàn)程悉罕,生產(chǎn)連接,達(dá)到配置的minIdle數(shù)量
- 標(biāo)記DataSource初始化完成
- lock.unlock()
理解
- 加鎖的主要作用
- 保證線(xiàn)程池初始化类早、運(yùn)行順序的正確性嗜逻。保證一定要在DataSource初始化完成以后,連接的創(chuàng)建栈顷、銷(xiāo)毀線(xiàn)程才有可能持有鎖,開(kāi)始生產(chǎn)和銷(xiāo)毀連接萄凤。
- 要操作共享變量,空閑連接池?cái)?shù)組DruidConnectionHolder[] connections坪圾。填充連接颤难,滿(mǎn)足配置的initialSize數(shù)量。
- 代理
- Druid的代理基本都是靜態(tài)代理模式