@yulongsun
2017-03-25T07:27:20.000000Z
字数 9335
阅读 1044
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();
}
@Override
public void close() throws SQLException {
System.err.println("连接关闭了......");
connections.addLast(this); //再次自己加回去
//realConnection.close();
//为了不影响以用户习惯的代码编写所以一个简单的类包裹实现代理,当用户关闭连接时,其实是将此连接更追加到链表的尾部。
//此功能可以一步步的引导学生完成,从最基本的强制用户调用一个方法将连接追加到尾部到实现自动的追加到尾部。
}
@Override
public void commit() throws SQLException {
realConnection.commit();
}
@Override
public Array createArrayOf(String typeName, Object[] elements)
throws SQLException {
return realConnection.createArrayOf(typeName, elements);
}
@Override
public Blob createBlob() throws SQLException {
return realConnection.createBlob();
}
@Override
public Clob createClob() throws SQLException {
return realConnection.createClob();
}
@Override
public NClob createNClob() throws SQLException {
return realConnection.createNClob();
}
@Override
public SQLXML createSQLXML() throws SQLException {
return realConnection.createSQLXML();
}
public Statement createStatement() throws SQLException {
return realConnection.createStatement();
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
return realConnection.createStatement(resultSetType, resultSetConcurrency);
}
@Override
public 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);
}
@Override
public boolean getAutoCommit() throws SQLException {
return realConnection.getAutoCommit();
}
@Override
public String getCatalog() throws SQLException {
return realConnection.getCatalog();
}
@Override
public Properties getClientInfo() throws SQLException {
return realConnection.getClientInfo();
}
@Override
public String getClientInfo(String name) throws SQLException {
return realConnection.getClientInfo(name);
}
public int getHoldability() throws SQLException {
return realConnection.getHoldability();
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return realConnection.getMetaData();
}
@Override
public int getTransactionIsolation() throws SQLException {
return realConnection.getTransactionIsolation();
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return realConnection.getTypeMap();
}
@Override
public SQLWarning getWarnings() throws SQLException {
return realConnection.getWarnings();
}
@Override
public boolean isClosed() throws SQLException {
return realConnection.isClosed();
}
@Override
public boolean isReadOnly() throws SQLException {
return realConnection.isReadOnly();
}
@Override
public boolean isValid(int timeout) throws SQLException {
return realConnection.isValid(timeout);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return realConnection.nativeSQL(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return realConnection.prepareCall(sql);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return realConnection.prepareCall(sql);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return realConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return realConnection.prepareStatement(sql);
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
return realConnection.prepareStatement(sql, autoGeneratedKeys);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
throws SQLException {
return realConnection.prepareStatement(sql, columnIndexes);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException {
return realConnection.prepareStatement(sql, columnNames);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return realConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return realConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
realConnection.releaseSavepoint(savepoint);
}
@Override
public void rollback() throws SQLException {
realConnection.rollback();
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
realConnection.rollback(savepoint);
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
realConnection.setAutoCommit(autoCommit);
}
@Override
public void setCatalog(String catalog) throws SQLException {
realConnection.setCatalog(catalog);
}
@Override
public void setClientInfo(Properties properties)
throws SQLClientInfoException {
realConnection.setClientInfo(properties);
}
@Override
public void setClientInfo(String name, String value)
throws SQLClientInfoException {
realConnection.setClientInfo(name, value);
}
@Override
public void setHoldability(int holdability) throws SQLException {
realConnection.setHoldability(holdability);
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
realConnection.setReadOnly(readOnly);
}
@Override
public Savepoint setSavepoint() throws SQLException {
return realConnection.setSavepoint();
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return realConnection.setSavepoint(name);
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
realConnection.setTransactionIsolation(level);
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
realConnection.setTypeMap(map);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return realConnection.isWrapperFor(iface);
}
@Override
public <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));//注意这个new
return c;
}
@Override
public 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);
}
}
}
}