@yulongsun
2017-03-25T07:27:20.000000Z
字数 9335
阅读 1176
java
为了实现对`对象Connection`的重用。
//创建自定义的连接池1、以下是类的源代码,使用的是MySql数据库,代码较多,请注意阅读。package cn.itcast.connectionpool;import java.sql.Array;import java.sql.Blob;import java.sql.CallableStatement;import java.sql.Clob;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.DriverManager;import java.sql.NClob;import java.sql.PreparedStatement;import java.sql.SQLClientInfoException;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.SQLXML;import java.sql.Savepoint;import java.sql.Statement;import java.sql.Struct;import java.util.LinkedList;import java.util.Map;import java.util.Properties;/*** 我的连接池* 通过此连接池的实现,用户只能通过 - 包装代理。* MyConnectionPool.getConnection()来获取连接* 且当用户关闭连接时并没有真的关闭,而是将此对连接又放回到LinkedList中。* @author <a href="wangjian_me@126.com">王健</a>*/public class MyConnectionPool {private MyConnectionPool(){}//声明一个私有的构造不允许别人创建//声明连接的字符串,可以使用动态加载,即从资源文件加载private static String url="jdbc:mysql://127.0.0.1:3306/itcast";//声明用户存放连接类private static LinkedList<Connection> connections = new LinkedList<Connection>();//仍然是在static中初始化static{try{Class.forName("com.mysql.jdbc.Driver");for(int i=0;i<5;i++){//声明初始化有5个连接Connection con = DriverManager.getConnection(url,"root","root");connections.addLast(new ItcastConnection(con));//退加到最后}System.err.println("共有几个连接:"+connections.size());}catch(Exception e){e.printStackTrace();}}/*** 获取一个连接*/public static Connection getConnection(){if(connections.size()<=0){throw new RuntimeException("已经没有可用的连接,或用户使用了连接后没有关闭。");}return connections.removeFirst();//返回第一个}/*** 声明成内部私有类,外部的任何人不可以访问* 以下使用了个"假"代理来完成Connection的功能* 请注意实现的close方法,并没有关闭连接。* @author <a href="wangjian_me@126.com">王健</a>*/static private class ItcastConnection implements Connection {private Connection realConnection; // 直接的连接/*** 私有的方法*/private ItcastConnection(Connection con){this.realConnection = con;}//下面的方法只是简单的调用realConnection的实现而已public void clearWarnings() throws SQLException {realConnection.clearWarnings();}@Overridepublic void close() throws SQLException {System.err.println("连接关闭了......");connections.addLast(this); //再次自己加回去//realConnection.close();//为了不影响以用户习惯的代码编写所以一个简单的类包裹实现代理,当用户关闭连接时,其实是将此连接更追加到链表的尾部。//此功能可以一步步的引导学生完成,从最基本的强制用户调用一个方法将连接追加到尾部到实现自动的追加到尾部。}@Overridepublic void commit() throws SQLException {realConnection.commit();}@Overridepublic Array createArrayOf(String typeName, Object[] elements)throws SQLException {return realConnection.createArrayOf(typeName, elements);}@Overridepublic Blob createBlob() throws SQLException {return realConnection.createBlob();}@Overridepublic Clob createClob() throws SQLException {return realConnection.createClob();}@Overridepublic NClob createNClob() throws SQLException {return realConnection.createNClob();}@Overridepublic SQLXML createSQLXML() throws SQLException {return realConnection.createSQLXML();}public Statement createStatement() throws SQLException {return realConnection.createStatement();}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency)throws SQLException {return realConnection.createStatement(resultSetType, resultSetConcurrency);}@Overridepublic Statement createStatement(int resultSetType,int resultSetConcurrency, int resultSetHoldability)throws SQLException {return realConnection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);}public Struct createStruct(String typeName, Object[] attributes)throws SQLException {return realConnection.createStruct(typeName, attributes);}@Overridepublic boolean getAutoCommit() throws SQLException {return realConnection.getAutoCommit();}@Overridepublic String getCatalog() throws SQLException {return realConnection.getCatalog();}@Overridepublic Properties getClientInfo() throws SQLException {return realConnection.getClientInfo();}@Overridepublic String getClientInfo(String name) throws SQLException {return realConnection.getClientInfo(name);}public int getHoldability() throws SQLException {return realConnection.getHoldability();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return realConnection.getMetaData();}@Overridepublic int getTransactionIsolation() throws SQLException {return realConnection.getTransactionIsolation();}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {return realConnection.getTypeMap();}@Overridepublic SQLWarning getWarnings() throws SQLException {return realConnection.getWarnings();}@Overridepublic boolean isClosed() throws SQLException {return realConnection.isClosed();}@Overridepublic boolean isReadOnly() throws SQLException {return realConnection.isReadOnly();}@Overridepublic boolean isValid(int timeout) throws SQLException {return realConnection.isValid(timeout);}@Overridepublic String nativeSQL(String sql) throws SQLException {return realConnection.nativeSQL(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return realConnection.prepareCall(sql);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType,int resultSetConcurrency) throws SQLException {return realConnection.prepareCall(sql);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType,int resultSetConcurrency, int resultSetHoldability)throws SQLException {return realConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return realConnection.prepareStatement(sql);}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)throws SQLException {return realConnection.prepareStatement(sql, autoGeneratedKeys);}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes)throws SQLException {return realConnection.prepareStatement(sql, columnIndexes);}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames)throws SQLException {return realConnection.prepareStatement(sql, columnNames);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType,int resultSetConcurrency) throws SQLException {return realConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType,int resultSetConcurrency, int resultSetHoldability)throws SQLException {return realConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {realConnection.releaseSavepoint(savepoint);}@Overridepublic void rollback() throws SQLException {realConnection.rollback();}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {realConnection.rollback(savepoint);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {realConnection.setAutoCommit(autoCommit);}@Overridepublic void setCatalog(String catalog) throws SQLException {realConnection.setCatalog(catalog);}@Overridepublic void setClientInfo(Properties properties)throws SQLClientInfoException {realConnection.setClientInfo(properties);}@Overridepublic void setClientInfo(String name, String value)throws SQLClientInfoException {realConnection.setClientInfo(name, value);}@Overridepublic void setHoldability(int holdability) throws SQLException {realConnection.setHoldability(holdability);}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {realConnection.setReadOnly(readOnly);}@Overridepublic Savepoint setSavepoint() throws SQLException {return realConnection.setSavepoint();}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {return realConnection.setSavepoint(name);}@Overridepublic void setTransactionIsolation(int level) throws SQLException {realConnection.setTransactionIsolation(level);}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {realConnection.setTypeMap(map);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return realConnection.isWrapperFor(iface);}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return realConnection.unwrap(iface);}}}

// 1、真实的代理实现应该使用InvocationHandler和Proxy两个类。// 2、代理的简单实现:见cn.itcast.proxy.a包。// 3、使用Proxy代理Connection类见:cn.itcast.proxy.b包// 以下是使用动态代理的源代码:package cn.itcast.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.util.LinkedList;/*** 数据库连接池* 使用动态代理实现* @author wangjianme*/public class MyConnPool {private static String driver = "com.mysql.jdbc.Driver";private static String url= "jdbc:mysql://127.0.0.1:3306/wj?useUincode=true&characterEncoding=utf8";//使用LinkedList保存有限的连接private static LinkedList<Connection> list = new LinkedList<Connection>();static{try{Class.forName(driver);for(int i=0;i<5;i++){Connection con = DriverManager.getConnection(url,"root","root");con = MyProxy.getConn(con);//对已经生成的Connection进行代理list.addLast(con);}}catch(Exception e){throw new RuntimeException(e.getMessage(),e);}}/*** 获取一个连接* @return*/public static Connection getConn(){if(list.size()>0){Connection con = list.removeFirst();return con;}else{throw new RuntimeException("已经没有可用的连接...");}}/*** 以下是动态代理类,实现执行句柄的接口* @author wangjianme*/static class MyProxy implements InvocationHandler{private Object o;private MyProxy(Object o){this.o = o;}public static Connection getConn(Object o){//对传过来的对像进行代理Connection c = (Connection)Proxy.newProxyInstance(o.getClass().getClassLoader(),new Class[]{Connection.class},new MyProxy(o));//注意这个newreturn c;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if(method.getName().equals("close")){System.err.println("有人在关闭连接,现在将它放回去:"+proxy);list.addLast((Connection)proxy);return null;}else{return method.invoke(o, args);}}}}