通过代理模式实现数据库连接池

实现数据库连接池

import javax.sql.DataSource;
import java.io.PrintWriter;
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.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

/**
 * @author 曲健磊
 * @date 2018-11-26 18:58:56
 * @description 自定义的数据库连接池
 */
public class MyDataSourcePool implements DataSource {

    /**
     * 初始化数据库连接四要素
     */
    private static String driver = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://192.168.220.111:3306/hive";
    private static String user = "hiveowner";
    private static String password = "Welcome_1";

    /**
     * 真正的连接池
     */
    private static LinkedList<Connection> dataSource = new LinkedList<>();
    static {
        try {
            // 注册驱动
            Class.forName(driver);
            // 一次性建立十个连接
            for (int i = 0; i < 10; i++) {
                dataSource.add(DriverManager.getConnection(url, user, password));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (dataSource.size() > 0) {
            // 得到一个连接,是真正的对象
            Connection conn = dataSource.removeFirst();

            // 生成代理对象
            Connection proxy = (Connection) Proxy.newProxyInstance(MyDataSourcePool.class.getClassLoader(),
                conn.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 重写close的逻辑
                        if (method.getName().equals("close")) {
                            dataSource.add(conn);
                            System.out.println("链接已经还池.....");
                            return null;
                        }
                        return method.invoke(conn, args);
                    }
            });
            return proxy;
        }
        throw new SQLException("系统忙,请稍后......");
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

测试自定义数据库连接池

package datasource;

import java.sql.Connection;
import java.sql.SQLException;

public class TestDataSourceMain {

	public static void main(String[] args) throws Exception {
		//从连接池中获取链接 使用完后  释放链接
		MyDataSourcePool pool = new MyDataSourcePool();
		
		for(int i=0;i<11;i++){
			Connection conn = pool.getConnection();//得到的链接是真正的数据库链接
			
			System.out.println("第"+i+"个链接,是"+ conn);
			
			conn.close(); //把数据库的链接还给了数据库,而不是连接池
		}
	}
}

这样在关闭连接的时候实际上是将连接返还数据库连接池,而不是真正的关闭,提高了连接的复用率。

关注我的微信公众号(曲健磊的个人随笔),观看更多精彩内容:
通过代理模式实现数据库连接池_第1张图片

你可能感兴趣的:(【设计模式】)