天天看点

自定义连接池

自定义连接池(管理连接)

代码实现:

    1.  MyPool.java  连接池类,   

    2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合

    3.  构造函数:循环创建3个连接

    4.  写一个创建连接的方法

    5.  获取连接

    ------>  判断: 池中有连接, 直接拿

     ------>          池中没有连接,

    ------->          判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,

            创建新的连接

    6. 释放连接

如何对Connection对象,生成一个代理对象:

|--java.lang.reflect.Proxy

         static Object newProxyInstance(

ClassLoader loader,    当前使用的类加载器

Class<?>[] interfaces,   目标对象(Connection)实现的接口类型

InvocationHandler h    事件处理器:当执行上面接口中的方法的时候,就会自动触发事件处理器代码,把当前执行的方法(method)作为参数传入。

)

代理的总结:(了解会用)

         使用代理,可以在不实现接口的情况,对接口的方法进行扩展,添加额外的用户需要的业务逻辑!

Demo

package com.cn.pool;
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;
/**
* Author:Liu Zhiyong
* Version:Version_1
* Date:2017年4月10日19:25:03
* Desc:自定义连接池, 管理连接
 代码实现:
  1.  MyPool.java  连接池类,   
  2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合
  3.  构造函数:循环创建3个连接
  4.  写一个创建连接的方法
  5.  获取连接
  ------>  判断: 池中有连接, 直接拿
   ------>          池中没有连接,
  ------->          判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,
      创建新的连接
  6. 释放连接
   ------->  连接放回集合中(..)
*/
public class MyPool {
  private int initCount = 3;//初始化连接数据
  private int maxCount = 6;//最大连接数
  private int currentCount = 0;//记录当前连接数
  //连接池(存放所有的初始化连接 )
  private LinkedList<Connection> pool = new LinkedList<Connection>();
  
  /**
   * 1.构造函数中,初始化连接放入连接池
   */
  public MyPool(){
    //初始化连接
    for(int i=0; i<initCount; i++){
      //记录当前连接
      currentCount++;
      //把连接加入连接池
      pool.add(this.createConnection());
    }
  }
  
  /**
   * 2.创建一个新的连接的方法(代理)
   * @return
   */
  private Connection createConnection(){
    try {
      //加载驱动程序
      Class.forName("com.mysql.jdbc.Driver");
      //原始的目标对象
      final Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
      
      /*****************对Connection对象代理***********************/
      //对conn创建其代理对象。返回一个指定接口的代理类实例
      Connection proxy = (Connection)Proxy.newProxyInstance(
          conn.getClass().getClassLoader(),// 定义代理类的类加载器。负责加载类的对象。
          new Class[]{Connection.class},//代理类要实现的接口列表
          new InvocationHandler(){// 当调用con对象方法的时候, 自动触发事务处理器
            @Override
            public Object invoke(Object proxy, Method method,
                Object[] args) throws Throwable {
              //方法返回
              Object result = null;
              // 当前执行的方法的方法名
              String methodName = method.getName();
              if("close".equals(methodName)){
                //连接放入连接池
                pool.add(conn);
              }else{
                result = method.invoke(conn, args); 调用目标对象方法
              }
              return result;
            }
            
          }//指派方法调用的调用处理程序 
      );
      return proxy;//返回代理对象
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  
  /**
   * 3.获取连接
   * @return
   */
  public Connection getConnection(){
    //3.1 判断连接池中是否有连接,如果有连接,就直接从连接池取出
    if(!pool.isEmpty()){
      return pool.removeFirst();//删除一个,并返回删除的对象Connection
    }
    //3.2连接池中没有连接:判断,如果没有达到最大连接数,创建
    if(currentCount < maxCount){
      //记录当前使用的连接数
      currentCount++;
      //创建连接
      return this.createConnection();
    }
    //3.3如果当前已经达到最大连接数,抛出异常
    throw new RuntimeException("当前连接已经达到最大连接数目");
  }
  
  /**
   * 4.释放连接(手动释放)
   */
  public void realeaseConnection(Connection conn){
    //4.1 判断,池的数目如果小于初始化连接,就放入池中
    if(pool.size() < initCount){
      pool.addLast(conn);
    }else{
      //4.2关闭
      try {
        currentCount--;//当前连接数-1
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace(); 
      }
    }
  }
  
  public static void main(String[] args) throws SQLException {
    MyPool pool = new MyPool();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    //使用连接
    Connection conn1 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    Connection conn2 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    Connection conn3 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    Connection conn4 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    Connection conn5 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    Connection conn6 = pool.getConnection();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    //释放连接,连接放回连接池
//    pool.realeaseConnection(conn1);
     /*
        希望:当关闭连接的时候,要把连接放入连接池!【当调用Connection接口的close方法时候,希望触发pool.addLast(con);操作】
      把连接放入连接池
          解决1:实现Connection接口,重写close方法
        解决2:动态代理
    */
    conn6.close();
    System.out.println("连接池:" + pool.pool.size() + "当前连接:" + pool.currentCount);
    //再获取
    pool.getConnection();
  }
}