美文网首页Java
自定义数据库连接池

自定义数据库连接池

作者: DouDouZH | 来源:发表于2018-10-17 11:21 被阅读0次

    一、自定义数据库连接池实现思想

    依赖的jar 依赖的jar包
    1、思想步骤
    • 1、链接池类
    • 2、制定全局参数,初始化数目,最大连接数,当前连接,链接池集合
    • 3、构造函数循环创建3个链接
    • 4、写一个从创建连接的方法
    • 5、获取连接
      判断有链接直接拿
      是否达到最大连接数,达到抛出异常
      没达到创建新连接
    • 6、释放链接 放回集合中
    • 7、优化连接 扩展close()方法 动态代理
    2、思想原理图 原理图
    3、优化:

    当关闭连接时候把链接放入连接池 就是调用clos()方法触发releaseConnection(Connection conn)方法
    *解决1:继承Connection重写clos方法 方法太多不可行
    *解决2:动态代理
    如果对某个接口中得到某个方法进行扩展,而不想实现接口所有的方法可以使用的动态代理模式
    java中代理模块:静态,动态,cglib代理
    动态代理可以及检测接口中方法的执行
    如何生成动态代理 jdk API提供Proxy

     static Object newProxyInstance{
         ClassLoader loader //当前使用的类加载器
         Class<?>interface //目标对象Connection实现的接口类型
         InvocationHabdler h //事件处理器,当执行上面接口中的方法的时候,  就自动触发处理器方法,把当前执行的发方法(method)作为参数传入
    }
    

    二、代码实现

    1、定义获取连接的接口DataSource.java
    package work.doudou.MyPool;
    
    import java.sql.Connection;
    //定义获取连接的接口
    public interface DataSource {
        public Connection getConnection();
    }
    
    2、数据源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、制定全局参数,初始化数目,最大连接数,当前连接,链接池集合
     * 3、构造函数循环创建3个链接
     * 4、写一个从创建连接的方法
     * 5、获取连接    
     *      判断有链接直接拿
     *      是否达到最大连接数,达到抛出异常 
     *      没达到创建新连接
     * 6、释放链接   放回集合中
     * 7、优化连接   扩展close()方法    动态代理
     **/
    
    /* 优化:
     * 当关闭连接时候把链接放入连接池     就是调用clos()方法触发releaseConnection(Connection conn)方法
     *      解决1:继承Connection重写clos方法   方法太多不可行
     *      解决2:动态代理
     *          如果对某个接口中得到某个方法进行扩展,而不想实现接口所有的方法可以使用的动态代理模式
     *          java中代理模块:静态,动态,cglib代理
     *          动态代理可以及检测接口中方法的执行
     *      如何生成动态代理 jdk API提供Proxy
     *          static Object newProxyInstance{
     *              ClassLoader loader 当前使用的类加载器
     *              Class<?>interface 目标对象Connection实现的接口类型
     *              InvocationHabdler h 事件处理器,当执行上面接口中的方法的时候,就自动触发
     *                                  处理器方法,把当前执行的发方法(method)作为参数传入
     *          }
     */
    public class BasicDataSource implements DataSource{
        //数据库连接账号
        private String username=null;
        //数据库连接密码
        private String password=null;
        //驱动com.mysql.jdbc.Driver
        private String driver=null;
        //数据库连接url  jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8","root","root
        private String url=null;
        //初始化数目
        private int init_count=3;
        //最大连接数
        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++){
                //记录当前连接数
                current_count++;
                //把链接放入连接池
                connections.addLast(createConnection());
            }
        }
        
        //2、建新连接的方法
        private Connection createConnection(){
            try {
                Class.forName(driver);
                //原始的目标对象
                final Connection conn= DriverManager.getConnection(url,username,password);
                /*******创建代理对象********/
                //创建代理对象
                Connection proxyConnection=(Connection)Proxy.newProxyInstance(
                        //类加载器
                        conn.getClass().getClassLoader(), 
                        //目标接口对象
                        new Class[] {Connection.class},
                        //当调用conn对象的时候自动触发事务处理器
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                //方法返回值
                                Object result=null;
                                //当前执行的方法名
                                String methoName=method.getName();  
                                //判断执行close()就把连接放入连接池
                                if ("close".equals(methoName)) {
                                    //连接放入连接池
                                    if(connections.size()<init_count){
                                        connections.addLast(conn);
                                    }else{
                                    //如果连接池满了就关了连接
                                        try {
                                            current_count--;
                                            conn.close();
                                        } catch (SQLException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                    }   
                                }else{
                                    //调用目标方法对象
                                    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();
            }
            //判断连接池有没有连接,如果没有达到最大连接,就创建
            if (current_count<max_count) {
                //记录当前连接使用数
                current_count++;
                //创建连接
                return createConnection();
            }
            //如果已达到最大连接数就,就抛出异常
            throw new RuntimeException("当前连接已达到最大连接数目!");
        }
        //4、释放链接
        public void releaseConnection(Connection conn) {
            //判断当前连接池数目如果少于初始化就放入池中
            if(connections.size()<init_count){
                connections.addLast(conn);
            }else{
            //如果连接池满了就关了连接
                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、测试类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 {
        //创建数据库连接池基础数据源的对象
        static BasicDataSource pool=new BasicDataSource();
        //设置基础数据
        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);
        }
        //返回连接池对象
        public static DataSource getDataSource() {
            return pool;
        }
        
        //测试主方法
        public static void main(String[] args) {    
            //获取数据库连接
            Connection connection=getDataSource().getConnection();
            //查询执行器
            Statement s=null;
            //返回结果集
            ResultSet rs=null;
            //控制台输出获取到连接的地址
            System.out.println(connection);
            try {
                //执行查询
                s=connection.createStatement();
                rs=s.executeQuery("select * from a");
                while (rs.next()) {
                    System.out.println(rs.getInt("a"));
                    
                }
                //关闭结果集
                rs.close();
                //关闭执行器
                s.close();
                //这里关闭连接是吧连接放回连接池
                connection.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("总共的连接数目"+pool.getCurrent_count());
            System.out.println("连接池里空闲的连接"+pool.getConnections().size());
      } 
    }
    
    

    三、运行结果

    运行结果

    相关文章

      网友评论

        本文标题:自定义数据库连接池

        本文链接:https://www.haomeiwen.com/subject/otvlzftx.html