利用 spring bean 的屬性 init-method 解決因為數據庫連接沒有初始化而導致首次點擊頁面超慢的問題


問題的描述:

一個項目,涉及到了 兩個數據源,分別使用的是 兩個不同的 數據庫連接池,其中一個是 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM