1 獲取Connection
DruidDataSource初始化完成后彪置,即可獲取connection與數(shù)據(jù)庫進(jìn)行交互了回官。
獲取如果有Filter,從filterChain中獲取connection,否則調(diào)用getConnectionDirect()直接獲取。
兩者返回的都是經(jīng)過封裝的DruidPooledConnection秸滴,類圖:
看下構(gòu)造函數(shù),需要傳入holder募判,從中獲取實(shí)際的Connection
擴(kuò)展定義了abandoned弧满、running身诺、disable和close的狀態(tài)
beforeExecute()和afterExecute() 處理running狀態(tài)的修改冒嫡,影響DataSource中的removeAbandoned(),執(zhí)行中的connection跳過清理
abandoned 在recycle()中影響是否回收
disable和close用處比較多涣雕,主要就是標(biāo)記連接是否可用
2 getConnection詳解
getConnectionDirect()方法開始,主要流程:
- 死循環(huán)開始直到獲取可用鏈接為止
- 調(diào)用getConnectionInternal獲取DruidPooledConnection
- 如果testOnBorrow為true装处,則進(jìn)行對連接進(jìn)行校驗(yàn)
- 如果testWhileIdle為true误债,距離上次激活時(shí)間超過timeBetweenEvictionRunsMillis,則進(jìn)行清理妄迁。
- 如果removeAbandoned為true寝蹈,則會(huì)把連接存放在activeConnections中,清理線程會(huì)對其定期進(jìn)行處理登淘。
getConnectionInternal()方法箫老,主要流程:
- 檢查等待線程數(shù)和錯(cuò)誤線程數(shù),超過設(shè)置了黔州,拋異常
- createScheduler存在且可用耍鬓,標(biāo)志位createDirect置為true阔籽,重新開始循環(huán),進(jìn)入直接創(chuàng)建連接流程牲蜀,創(chuàng)建新的物理連接和holder仿耽,加鎖校驗(yàn)連接數(shù)有沒有超設(shè)置,超過便discord各薇,否則即完成創(chuàng)建
- 調(diào)用pollLast(nanos)-有超時(shí),或者 takeLast()獲取holder君躺,如果獲取holder失敗峭判,構(gòu)建異常消息,拋異常
- 否則棕叫,以holder為參new一個(gè)DruidPooledConnection返回
takeLast()主要就是從連接數(shù)組中獲取最后一個(gè)可用的返回
獲取到鏈接之后林螃,就可以調(diào)用conn.prepareStatement來執(zhí)行sql了
3 連接回收
DruidPooledConnection實(shí)現(xiàn)了JDBC的close方法,
從holder中獲取Datasource俺泣,判斷當(dāng)前線程是否歸屬線程疗认,不是的話,就加鎖關(guān)閉
否則直接進(jìn)行關(guān)閉
分發(fā)當(dāng)前連接關(guān)閉的事件到ConnectionEventListener
最終都到recycle()方法中進(jìn)行回收伏钠,而不是真正的關(guān)閉横漏,主要流程如下:
同樣判斷當(dāng)前線程是否歸屬線程,不是的話熟掂,就加鎖操作
將當(dāng)前線程從活躍線程組 activeConnections 中移除缎浇,主要是方便后面的丟棄或者回收的工作。
然后檢查是否需要進(jìn)行回滾赴肚,不需要繼續(xù)往下走素跺。
reset 當(dāng)前 connection 的 holder 的相關(guān)配置。
接下來是對各項(xiàng)信息進(jìn)行檢查誉券,主要是看連接是否還可以重用指厌。
鎖住然后進(jìn)行真正的回收工作,這里回收交給了 putLast 方法踊跟。
putLast 呼應(yīng)前面的takeLast踩验,就是把連接放回connections數(shù)組中
4 總結(jié)
獲取和回收連接的過程中,定義了一大堆狀態(tài)和計(jì)數(shù)器琴锭,主要用于統(tǒng)計(jì)和各種加鎖的場景晰甚,鎖的粒度已經(jīng)控制得非常精細(xì)了。比想象地要復(fù)雜很多决帖,鎖的粒度精細(xì)化有助于提高并發(fā)場景的性能厕九,但是帶來的代碼復(fù)雜度的提升不是一點(diǎn)點(diǎn)。實(shí)際工程中地回,不僅要平衡兩者扁远,還要對自己加鎖的操作俊鱼,有100%的確信度。