您現在的位置是:首頁 > 棋牌

如何使用動態代理,自己寫一個數據庫連線池?

  • 由 劉小愛 發表于 棋牌
  • 2022-07-16
簡介自定義一個類MyConn實現Java中的Connection介面:①構造方法我們要將close方法改造成將連線還回連線池,肯定要傳進來一個我們正在使用的連線池

資料庫介面怎麼寫

今天是劉小愛自學Java的第68天。

感謝你的觀看,謝謝你。

話不多說,開始今天的學習:

如何使用動態代理,自己寫一個數據庫連線池?

在學執行緒的時候,學過執行緒池的概念。

當時舉了個地鐵臨時票的例子,來說明執行緒池的作用。

其實資料庫連線池也是一樣的道理。

也就是將資料庫連線放到一個池子裡面,需要使用時就去取,這樣的話,就不用每次都自己獲取連線了。

用一張圖片來說明:

如何使用動態代理,自己寫一個數據庫連線池?

①普通方式獲取連線

使用者每訪問一次資料庫就要獲取一次連線,這樣就會有幾個問題:

連線使用完後就會被銷燬,造成資源浪費。

如果使用者有很多個,要獲取很多次連線。

頻繁的連線資料會造成資源消耗過多,從而使資料庫宕機。

②連線池獲取連線

連線池的好處在於:

每次使用完連線後將其放回連線池,資源重複利用,更能提高程式效能。

無論多少個使用者,都只需要從連線池中獲取就可以了。

一、自定義連線池

事實上關於連線池已經有框架將其封裝好了,我們可以直接用。但現在是學習階段,知其然也要知其所以然。

我們不妨自定義一個連線池,看看具體是如何操作的,並且這樣也能更好地去學習連線池框架。

如何使用動態代理,自己寫一個數據庫連線池?

①實現DataSource介面

dataSource是Java中的一個介面,也是Java制定的一個規範,不同的連線池都需要實現這個介面。

MyDataSource是我們自定義的一個連線池,自然也是需要實現該介面。

②建立連線池容器

為什麼要用LindkedList?

連線池中的連線被取走,相當於刪除了該連線。

使用者用完連線將其還回連線池,相當於增加了該連線。

所以連線池要經常地進行增加和刪除。

LinkedList集合的底層是連結串列,特點增刪快查詢慢,所以選擇使用LinkedList。

③初始化連線池

也就是自定義連線池的構造方法,透過引數count可以指定連線池中連線的數量。

④從連線池中獲取連線

從連線池中拿走了一個連線,也就相當於將連線池中的該連線刪除了。

⑤用完將連線還回來

自定義一個backToPool()方法。

使用完連線後呼叫該方法將連線還回來。

這也就相當於將該連線新增進連線池中。

自定義連線池寫完,做一個測試:

如何使用動態代理,自己寫一個數據庫連線池?

①建立連線池

我們這邊給連線池初始化6個連線。

②獲取連線

現在只需要從連線池中獲取連線就好了。

③預編譯以及處理結果

這個昨天剛學習過,不再贅述。

④釋放資源

使用昨天封裝在工具類JdbcUtil類中的release()方法,其中連線不需要被釋放掉,用null代替。

⑤連線還回

連線使用完了之後將其還回到連線池中。

二、最佳化一之裝飾模式

自定義連線池有一個問題,我們定義了一個方法backToPool(),也就是將用完連線將其還回到連線池。

對於我們開發者來說還得自己記住這個方法名,特繁瑣。

有沒有什麼方法直接就能達到其目的?

答案是有的。我們每次使用完連線都要close(),也就是上述中被封裝在工具類JdbcUtil類裡的release()方法。

將連線的close方法裡面的業務邏輯改成將連線還會連線池就好了。

我們看看close方法的原始碼:

如何使用動態代理,自己寫一個數據庫連線池?

①Java中的close方法

Java中有一個介面就是Connection介面,其中就有close方法。這個介面就是Java制定的一個數據庫規範。

任何資料庫要連線Java就得實現Connection介面。

②MySQL中的close方法

我們使用的資料庫是MySQL,MySQL它本身也確實實現了Java中的Connection介面(ConnectionImpl這個類)

也就是MySQL官網上下載的驅動,匯入架包直接可以用。

至於其close方法具體是如何寫的,我們不用管。

好現在我們弄明白了close方法到底是個什麼回事,要改造close方法。

要知道Connection中是有很多很多方法的,並不是只有一個close方法。

在我們所學的知識中,有什麼方法可以實現該目的?

繼承就可以了:自定義一個類MyConn,繼承MySQL中的ConnectionImpl類,只重寫close方法,其它方法都不管。

既然有繼承,那裝飾設計模式也可以。

並且裝飾設計模式比繼承更有拓展性。

自定義一個類MyConn實現Java中的Connection介面:

如何使用動態代理,自己寫一個數據庫連線池?

①構造方法

我們要將close方法改造成將連線還回連線池,肯定要傳進來一個我們正在使用的連線池。

此外還需要一個連線,根據面向介面程式設計原則:

引數設定成Java中的父介面Connection。

具體傳參時,用mysql寫的實現類連線也行,用oracle寫的實現類連線也行。

②改造close方法

釋放資源時會有一個這樣的操作:coon。close()。

它本來的所有是將連線conn銷燬掉,但我們現在不銷燬而是要將其重寫放回到連線池中。

所以具體的業務邏輯就是:pool。addLast(this)。

這個this就是指的coon,誰呼叫了close方法,這裡的this指的就是誰。

③其它方法不改造

mysql中的連線是如何處理的,我們直接呼叫就好了。

所以其它方法都沒有具體的業務邏輯,而是直接讓傳進來來的conn去處理。

其它方法是有很多個的,我隨便截一個圖:

如何使用動態代理,自己寫一個數據庫連線池?

方法一大堆,這還僅僅只是一部分,還有很多,沒法一下子截圖下來。

這個裝飾設計模式也就類似於當初學動態代理說的

明星與經紀人

案例:

mysql中的連線,就相當於具體某個明星;

我自定義的連線類,就相當於該明星的經紀人。

經紀人只做溝通,具體怎麼操作還是要靠明星。

自定義的連線類只修改close方法,其它還是要靠mysql中的連線。

既然如何,那何不用動態代理?

三、最佳化二之動態代理

前面屁顛屁顛第說了這麼一大堆,其實就是為了引出動態代理這個概念。

因為動態代理比較難理解,所以一步一步說明。

我們再做一個梳理:

首先Java中有一個連線介面Connection。

其次MySQL中有一個連線類實現了Java中的這個介面,具體怎麼實現的,我們不用管。

最後我們要將MySQL連線中的close方法做一個改造,同時其它的方法都不用改變。

也就是說我們需要去代理MySQL中的連線。

現在使用動態代理進行改造:

如何使用動態代理,自己寫一個數據庫連線池?

①從連線池中獲取連線

這個連線是什麼?是MySQL中寫好的實現類連線。

②動態代理改造

三個引數:

conn的類載入器。

被代理類所要實現的介面 ,也就是Java中的Connection介面。

呼叫處理器。

動態代理的核心其實就是這個呼叫處理器

後續connProxy呼叫close方法也好,呼叫其它方法也罷,其都會做一件事情:呼叫處理器呼叫invoke方法。

③返回代理類連線物件

這個已經是改造好了的,也就是說我們從連線池中獲取連線,本來是MySQL中的,但是我們現在將其改造了。

所以後續用conn操作時,其實用的就是這個改造後的代理類連線物件。

④如果是close方法

後續conn呼叫close方法,就將其改造成我們想要的業務邏輯,也就是將連線新增到連線池中。

⑤如果是其他方法

後續conn呼叫其它方法(也就是connection介面中的那一堆方法),我們不用管,直接利用反射就好了。

動態代理的好處之一也在於此,其它的有哪些方法,方法名叫什麼,怎麼實現的,統統都不用管。

動態代理只關注我們需要的方法本身,其他不用管,比裝飾設計模式更加地簡潔。

以上便是用動態代理自定義的一個連線池,當然已經有開源的連線池,可以直接拿來用,不用自己寫。

我寫一遍的目的也就是想更好地去學習那些開源連線池。

最後

謝謝你的觀看。

如果可以的話,麻煩幫忙點個贊,謝謝你。

Top