2013-02-06 50 views
1

我已經實現了連接池。一切都很好。現在,如果一個客戶借用一個連接,甚至將其返回到池中,但客戶端也保持與他的連接的參考。現在,如果池返回與另一個客戶端相同的連接,這將導致多人使用相同的連接。避免客戶端在實現連接時保持連接的引用池

我該如何避免這種情況?

回答

1

不要返回底層連接對象,而是返回包裝它的另一個對象。在該對象內(使用某種私有屬性)存儲該對象的狀態;是否仍然可以使用,還是因爲被退回游泳池或其他條件(如超時)而失效)。然後你可以攔截任何嘗試使用它的方法調用並檢查它的狀態。如果它不再可用,則拋出異常。

包裝的連接對象也需要是私有的,這樣客戶端才能直接訪問它。

每個客戶端都有一個包裝器,但兩個或多個包裝器可能共享底層連接對象。但是,由於每個客戶端都在存儲狀態,因此一次只能有一個客戶端使用該對象。

修改爲包含一個未經測試的示例 - 該示例現在顯示了我的方法存在的一個大問題。

假設你正在返回一些實現了java.sql.Connection的東西,你可以返回下面類的實例。

package same.package.as.your.pool; // so your pool has access to set isValidConnection 

import java.sql.Connection; 

class MyConnection implements Connection { 
    private Connection actualConnection; 
    private boolean isValidConnection = false; 

    MyConnection(Connection conn) { 
     // package acccess for pool class to create connection 
     actualConnection = conn; 
     isValidConnection = true; 
    } 

    public boolean getIsValidConnection() { 
     return isValidConnection; 
    } 

    void setIsValidConnection(boolean isValid) { 
     // pool class can call this to invalidate when returned to pool or timed out 
     isValidConnection = isValid; 
    } 

    // intercept java.sql.Connection methods, checking if connection is still valid first 
    // for example 
    PreparedStatement prepareStatement(String sql) { 
     if (! isValidConnection) { 
      // WHAT TO DO HERE? 
     } 
     return actualConnection.prepareStatement(sql); 

    } 

    // ... and the rest 

第一個大問題就是 - 最好你會當連接不再有效,因爲它已經返回到池塘裏扔從像prepareStatement方法異常。但是由於受到捕獲的原始接口異常的限制(在本例中拋出SQLException),您需要拋出一個SQLException(yuk,它實際上不是一個SQLException)或一個未捕獲的異常(yuk - 客戶機代碼可能想要捕捉連接池不再有效的情況)或其他: - )

上述代碼的兩個其他問題 - 用於保護只​​能用於池代碼的方法的包訪問是不是很健壯。也許你可以創建MyConnection代碼作爲池代碼中的某種內部類。最後,必須重寫全部 java.sql.Connection接口將會很痛苦。

}

+0

我不確定這是如何「真實」的連接池做到這一點,只是我的想法如何處理它。 –

+0

你可以舉個例子!我瞭解包裝對象;但即使返回object()。getConnection()返回該對象;客戶端仍然可以參考。 – Deepak

+0

你正在返回的類實例不應該有getConnection()。 –