自定義數(shù)據(jù)庫(kù)連接池

一、自定義數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)思想

依賴的jar
依賴的jar包
1、思想步驟
  • 1、鏈接池類
  • 2、制定全局參數(shù),初始化數(shù)目,最大連接數(shù),當(dāng)前連接,鏈接池集合
  • 3、構(gòu)造函數(shù)循環(huán)創(chuàng)建3個(gè)鏈接
  • 4、寫一個(gè)從創(chuàng)建連接的方法
  • 5、獲取連接
    判斷有鏈接直接拿
    是否達(dá)到最大連接數(shù),達(dá)到拋出異常
    沒達(dá)到創(chuàng)建新連接
  • 6、釋放鏈接 放回集合中
  • 7、優(yōu)化連接 擴(kuò)展close()方法 動(dòng)態(tài)代理
2、思想原理圖
原理圖
3、優(yōu)化:

當(dāng)關(guān)閉連接時(shí)候把鏈接放入連接池 就是調(diào)用clos()方法觸發(fā)releaseConnection(Connection conn)方法
*解決1:繼承Connection重寫clos方法 方法太多不可行
*解決2:動(dòng)態(tài)代理
如果對(duì)某個(gè)接口中得到某個(gè)方法進(jìn)行擴(kuò)展,而不想實(shí)現(xiàn)接口所有的方法可以使用的動(dòng)態(tài)代理模式
java中代理模塊:靜態(tài),動(dòng)態(tài),cglib代理
動(dòng)態(tài)代理可以及檢測(cè)接口中方法的執(zhí)行
如何生成動(dòng)態(tài)代理 jdk API提供Proxy

 static Object newProxyInstance{
     ClassLoader loader //當(dāng)前使用的類加載器
     Class<?>interface //目標(biāo)對(duì)象Connection實(shí)現(xiàn)的接口類型
     InvocationHabdler h //事件處理器,當(dāng)執(zhí)行上面接口中的方法的時(shí)候,  就自動(dòng)觸發(fā)處理器方法,把當(dāng)前執(zhí)行的發(fā)方法(method)作為參數(shù)傳入
}

二、代碼實(shí)現(xiàn)

1、定義獲取連接的接口DataSource.java
package work.doudou.MyPool;

import java.sql.Connection;
//定義獲取連接的接口
public interface DataSource {
    public Connection getConnection();
}
2、數(shù)據(jù)源BasicDataSource.java
package work.doudou.MyPool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;


/**
 * 自定義鏈接池
 * 1、MyPool.java類,鏈接池類
 * 2、制定全局參數(shù),初始化數(shù)目,最大連接數(shù),當(dāng)前連接,鏈接池集合
 * 3、構(gòu)造函數(shù)循環(huán)創(chuàng)建3個(gè)鏈接
 * 4、寫一個(gè)從創(chuàng)建連接的方法
 * 5、獲取連接    
 *      判斷有鏈接直接拿
 *      是否達(dá)到最大連接數(shù),達(dá)到拋出異常 
 *      沒達(dá)到創(chuàng)建新連接
 * 6、釋放鏈接   放回集合中
 * 7、優(yōu)化連接   擴(kuò)展close()方法    動(dòng)態(tài)代理
 **/

/* 優(yōu)化:
 * 當(dāng)關(guān)閉連接時(shí)候把鏈接放入連接池     就是調(diào)用clos()方法觸發(fā)releaseConnection(Connection conn)方法
 *      解決1:繼承Connection重寫clos方法   方法太多不可行
 *      解決2:動(dòng)態(tài)代理
 *          如果對(duì)某個(gè)接口中得到某個(gè)方法進(jìn)行擴(kuò)展,而不想實(shí)現(xiàn)接口所有的方法可以使用的動(dòng)態(tài)代理模式
 *          java中代理模塊:靜態(tài),動(dòng)態(tài),cglib代理
 *          動(dòng)態(tài)代理可以及檢測(cè)接口中方法的執(zhí)行
 *      如何生成動(dòng)態(tài)代理 jdk API提供Proxy
 *          static Object newProxyInstance{
 *              ClassLoader loader 當(dāng)前使用的類加載器
 *              Class<?>interface 目標(biāo)對(duì)象Connection實(shí)現(xiàn)的接口類型
 *              InvocationHabdler h 事件處理器,當(dāng)執(zhí)行上面接口中的方法的時(shí)候,就自動(dòng)觸發(fā)
 *                                  處理器方法,把當(dāng)前執(zhí)行的發(fā)方法(method)作為參數(shù)傳入
 *          }
 */
public class BasicDataSource implements DataSource{
    //數(shù)據(jù)庫(kù)連接賬號(hào)
    private String username=null;
    //數(shù)據(jù)庫(kù)連接密碼
    private String password=null;
    //驅(qū)動(dòng)com.mysql.jdbc.Driver
    private String driver=null;
    //數(shù)據(jù)庫(kù)連接url  jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8","root","root
    private String url=null;
    //初始化數(shù)目
    private int init_count=3;
    //最大連接數(shù)
    private int max_count=5;
    //連接池里頭的連接
    private int current_count=0;
    //連接池,存放鏈接
    private LinkedList<Connection> connections=new LinkedList<Connection>();
    
    
    //1、初始化連接放入連接池  
    private void createBasicDataSource(){
    //初始化連接
        for(int i=0;i<init_count;i++){
            //記錄當(dāng)前連接數(shù)
            current_count++;
            //把鏈接放入連接池
            connections.addLast(createConnection());
        }
    }
    
    //2、建新連接的方法
    private Connection createConnection(){
        try {
            Class.forName(driver);
            //原始的目標(biāo)對(duì)象
            final Connection conn= DriverManager.getConnection(url,username,password);
            /*******創(chuàng)建代理對(duì)象********/
            //創(chuàng)建代理對(duì)象
            Connection proxyConnection=(Connection)Proxy.newProxyInstance(
                    //類加載器
                    conn.getClass().getClassLoader(), 
                    //目標(biāo)接口對(duì)象
                    new Class[] {Connection.class},
                    //當(dāng)調(diào)用conn對(duì)象的時(shí)候自動(dòng)觸發(fā)事務(wù)處理器
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //方法返回值
                            Object result=null;
                            //當(dāng)前執(zhí)行的方法名
                            String methoName=method.getName();  
                            //判斷執(zhí)行close()就把連接放入連接池
                            if ("close".equals(methoName)) {
                                //連接放入連接池
                                if(connections.size()<init_count){
                                    connections.addLast(conn);
                                }else{
                                //如果連接池滿了就關(guān)了連接
                                    try {
                                        current_count--;
                                        conn.close();
                                    } catch (SQLException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                }   
                            }else{
                                //調(diào)用目標(biāo)方法對(duì)象
                                result=method.invoke(conn, args);
                            }
                            
                            return result;
                        }
                    }); 
            return proxyConnection;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    //3、獲取連接
    @Override
    public Connection getConnection() {
        //獲取連接之前判斷是否初始化
        if (connections.size()<=0) {
            createBasicDataSource();
        }
        //判斷是否連接,有就去出,,就直拿
        if (connections.size()>0) {
            return connections.removeFirst();
        }
        //判斷連接池有沒有連接,如果沒有達(dá)到最大連接,就創(chuàng)建
        if (current_count<max_count) {
            //記錄當(dāng)前連接使用數(shù)
            current_count++;
            //創(chuàng)建連接
            return createConnection();
        }
        //如果已達(dá)到最大連接數(shù)就,就拋出異常
        throw new RuntimeException("當(dāng)前連接已達(dá)到最大連接數(shù)目!");
    }
    //4、釋放鏈接
    public void releaseConnection(Connection conn) {
        //判斷當(dāng)前連接池?cái)?shù)目如果少于初始化就放入池中
        if(connections.size()<init_count){
            connections.addLast(conn);
        }else{
        //如果連接池滿了就關(guān)了連接
            try {
                current_count--;
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getInit_count() {
        return init_count;
    }

    public void setInit_count(int init_count) {
        this.init_count = init_count;
    }

    public int getMax_count() {
        return max_count;
    }

    public void setMax_count(int max_count) {
        this.max_count = max_count;
    }

    public int getCurrent_count() {
        return current_count;
    }

    public LinkedList<Connection> getConnections() {
        return connections;
    }   
}

3、測(cè)試類test.java
package work.doudou.MyPool;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class test {
    //創(chuàng)建數(shù)據(jù)庫(kù)連接池基礎(chǔ)數(shù)據(jù)源的對(duì)象
    static BasicDataSource pool=new BasicDataSource();
    //設(shè)置基礎(chǔ)數(shù)據(jù)
    static{
        pool.setUsername("root");
        pool.setPassword("root");
        pool.setDriver("com.mysql.jdbc.Driver");
        pool.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
        pool.setInit_count(5);
        pool.setMax_count(7);
    }
    //返回連接池對(duì)象
    public static DataSource getDataSource() {
        return pool;
    }
    
    //測(cè)試主方法
    public static void main(String[] args) {    
        //獲取數(shù)據(jù)庫(kù)連接
        Connection connection=getDataSource().getConnection();
        //查詢執(zhí)行器
        Statement s=null;
        //返回結(jié)果集
        ResultSet rs=null;
        //控制臺(tái)輸出獲取到連接的地址
        System.out.println(connection);
        try {
            //執(zhí)行查詢
            s=connection.createStatement();
            rs=s.executeQuery("select * from a");
            while (rs.next()) {
                System.out.println(rs.getInt("a"));
                
            }
            //關(guān)閉結(jié)果集
            rs.close();
            //關(guān)閉執(zhí)行器
            s.close();
            //這里關(guān)閉連接是吧連接放回連接池
            connection.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("總共的連接數(shù)目"+pool.getCurrent_count());
        System.out.println("連接池里空閑的連接"+pool.getConnections().size());
  } 
}

三、運(yùn)行結(jié)果

運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容