問題的描述: 一個項目,涉及到了 兩個數據源,分別使用的是 兩個不同的 資料庫連接池,其中一個是 poxool 連接池,問題在於,spring在啟動時,只初始化其中的一個 資料庫連接池中的資料庫連接,而 poxool配置的資料庫連接池,在啟動時 沒有進行初始化,一個資料庫連接也沒有初始化好,所以導致 ...
問題的描述:
一個項目,涉及到了 兩個數據源,分別使用的是 兩個不同的 資料庫連接池,其中一個是 poxool 連接池,問題在於,spring在啟動時,只初始化其中的一個 資料庫連接池中的資料庫連接,而 poxool配置的資料庫連接池,在啟動時 沒有進行初始化,一個資料庫連接也沒有初始化好,所以導致了首次需要 訪問資料庫時,臨時需要進行資料庫連接的初始化,導致了首次點擊頁面按鈕時,如果是遠程訪問,最多需要15秒左右。
一開始以為可以在 dataSource 這個bean 上使用屬性 lazy-init = "false" 來搞定,其實預設就是 lazy-init="false",其實從 spring 的啟動日誌來看,poxool 對應的 dataSource已經實例化了,所以不是 dataSource 延遲初始化的問題,而是 dataSoruce 實例化了,但是其中的 資料庫連接卻沒有初始化,所以這才是問題的根本原因。
找到了原因,那麼解決起來就容易了,我們知道 bean 有個屬性: init-method ="someMethod",表示在實例化 bean的後期階段,調用 該 bean 的 someMethod 方法。
所以,我們查看 org.logicalcobwebs.proxool.ProxoolDataSource 的源碼,找到他的初始化資料庫連接的 方法,賦值該 init-method 屬性就可以搞定了。源碼如下:
/** * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() throws SQLException { ConnectionPool cp = null; try { if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { registerPool(); } cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); return cp.getConnection(); } catch (ProxoolException e) { LOG.error("Problem getting connection", e); throw new SQLException(e.toString()); } }
很顯然,getConnection 會觸發了 org.logicalcobwebs.proxool.ProxoolDataSource 建立資料庫連接。
所以將 bean:
<bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
改為:
<bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource" init-method="getConnection">
就OK了,會強制 org.logicalcobwebs.proxool.ProxoolDataSource 在實例化時,立即調用 getConnection方法,立即初始化好資料庫連接。
避免直到第一次訪問資料庫時,才臨時去初始化資料庫連接池,從而導致的首次訪問超級慢的問題。
這樣配置的話,會導致另一個小小的問題,啟動時,會變慢一點,因為啟動時,需要出事化兩個資料庫連接池中的資料庫連接。
關於 init-method的原理,可以參考我的另一篇博客:http://www.cnblogs.com/digdeep/p/4518571.html