连接池原理:通过一次性从数据库中取出多个Connection连接放入到一个集合中,当用户需要用到Connection连接时可以从集合中取出来,而不用频繁从数据库中获取连接对象,
大大提高了数据库的性能,使用代理模式可以监看到当用户调用close关闭连接的方法时,将当前连接放入到集合中,从而达到复用的效果!
1.数据库连接工具类:
package mybatis.tools; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 用于获取数据库连接对象 * @author lance * */ public class DBUtils { private static String driver = "com.mysql.jdbc.Driver"; private static String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=true&useUnicode=true&characterEncoding=utf-8"; private static String user = "root"; private static String password = "root"; /*在静态代码块中加载驱动, 静态代码块在加载class文件的会执行,且只执行一次*/ static { try { Class.forName(driver); } catch(Exception e) { e.printStackTrace(); } } /**提供获取Connection对象的方法*/ public static Connection getConnection() { //通过驱动管理器获取一个连接对象 Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch(SQLException e) { e.printStackTrace(); } return conn; } }
2.定义连接池工具类:
package mybatis.tools; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.util.LinkedList; /** * 描述: * 连接池 * * @author lance * @create 2018-10-16 9:42 */ public class ConnectionProxy { /** * 连接池集合 * 用到LinkedList集合是因为这是一个链表结构,我们可以很方便从头部取出连接, * 从底部放入连接(LinkedList的优点) */ private static LinkedList<Connection> pool = new LinkedList<>(); /** * 初始化连接池的大小 * @param initSize */ public ConnectionProxy(int initSize){ for (int i = 0; i < initSize; i++) { //获取连接 Connection conn = DBUtils.getConnection(); //对连接进行代理(先代理好连接再放入到集合中是因为不用在集合中 // 再一个个取出来再进行代理,效率快) conn = createProxy(conn); //放入到集合中 pool.add(conn); } } /** * 从连接池中拿出连接 * @return */ public Connection getConnection(){ if(pool.size() > 0){ return pool.removeFirst(); } //如果集合中没有连接则抛出异常 throw new RuntimeException("连接池没有可用连接!"); } /** * 对Connection进行代理 * @param conn * @return */ private Connection createProxy(Connection conn) { return (Connection) Proxy.newProxyInstance( // 类加载器 conn.getClass().getClassLoader(), // 目标对象实现的接口 new Class[]{Connection.class}, // 当调用con对象方法的时候, 自动触发事务处理器 new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 判断当执行了close方法的时候,把连接放入连接池 if ("close".equals(method.getName())) { pool.addLast((Connection)proxy); return null; } Object returnValue = method.invoke(conn,args); return returnValue; } }); } /** * 查看连接池的大小 * @return */ public int size(){ return pool.size(); } public static void main(String[] args) throws Exception{ ConnectionProxy connectionProxy = new ConnectionProxy(10); System.out.println(connectionProxy.size()); Connection connection = connectionProxy.getConnection(); System.out.println(connectionProxy.size()); connection.close(); System.out.println(connectionProxy.size()); } }
效果图