这是一个连接池的小例子,连接池需要实现DataSource接口,使用Object.class.getClassLoader().getResourceAsStream("")加载文件,然后new一个Properties的对象来装载输入流,读取所需要的配置信息,使用Collections.synchronizedList来保证线程安全,使用linkedList集合存取连接对象。
总体实现思路:使用DriverManager.getConnection来获得数据库连接,获取自定义的连接个数,然后将这些都add到集合中,然后当需要调用连接对象时,首先判断连接池的个数是不是大于0,是就把集合中连接池对象remove掉,同时把这个remove掉的对象赋给需要调用的程序,如果连接池中所剩的对象为0,则抛出运行时异常。当获得数据库连接对象后,就动态返回,动态返回时,当调用的是数据库的close方法,就把对象重新添加到集合中,否则返回原对象调用的方法,代码如下
package com.freshbin.pool;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
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.sql.SQLFeatureNotSupportedException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
public class JdbcPool implements DataSource {
// 创建一个集合来保存所有的数据库连接,当程序需要连接数据库时,则从集合中获取,同时调用集合的remove方法
// 因为集合的remove方法返回的正是你集合中的对象,所有正好可以将从集合中remove的连接对象赋给程序
// 当关闭数据库时,则调用集合的add方法,将连接返回给集合
// 使用Collections工具类,使集合是线程安全的
private static List<Connection> connList = Collections
.synchronizedList(new LinkedList<Connection>());
static {
// 通过java的反射加载配置文件
InputStream is = JdbcPool.class.getClassLoader().getResourceAsStream(
"conf/jdbc.properties");
// 创建一个pro对象,方便从配置文件中读取文件
Properties pro = new Properties();
// 加载文件流,读取内容
try {
pro.load(is);
String drive = pro.getProperty("driver");
String url = pro.getProperty("url");
String username = pro.getProperty("username");
String password = pro.getProperty("password");
int jdbcPoolInitSize = Integer.parseInt(pro
.getProperty("jdbcPoolInitSize"));
//加载驱动
Class.forName(drive);
for (int i = 0; i < jdbcPoolInitSize; i++) {
Connection conn = DriverManager.getConnection(url, username, password);
System.out.println("获取到了数据库连接:" + conn);
//将数据库连接存到集合中
connList.add(conn);
}
System.out.println("数据库连接池的总共个数:" + connList.size());
System.out.println("----------------------------------------------------");
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Connection getConnection() throws SQLException {
//首先判断集合中有没有空闲的数据库连接对象,如果没有则直接抛出异常,不再返回
if(connList.size() > 0) {
//返回一个连接对象,集合调用remove的同时即可返回一个对象
final Connection conn = connList.remove(0);
System.out.println("被拿走了一个连接:" + conn);
System.out.println("数据库连接池的个数:" + connList.size());
//使用动态代理返回
return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//如果调用的是close方法,则将数据库连接对象重新加入到集合中
if("close".equals(method.getName())) {
connList.add(conn);
System.out.println("数据库对象已回收:" + conn);
System.out.println("连接池的个数:" + connList.size());
System.out.println("----------------------------------------------------");
return null;
} else {
return method.invoke(conn, args);
}
}
});
} else {
throw new RuntimeException("暂时没有空闲的数据库对象可以使用!请等等。。。");
}
}
@Override
public Connection getConnection(String arg0, String arg1)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
然后工具类兼测试类的代码如下
package com.freshbin.util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.freshbin.pool.JdbcPool;
public class JdbcUtil {
private static JdbcPool pool = new JdbcPool();
public static Connection getConnection() throws SQLException {
return pool.getConnection();
}
public static void close(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
// 关闭存储查询结果的ResultSet对象
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
// 关闭负责执行SQL命令的Statement对象
st.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
// 关闭Connection数据库连接对象
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
Connection conn = JdbcUtil.getConnection();
System.out.println("拿连接:" + conn);
System.out.println("-------------------------------");
conn = JdbcUtil.getConnection();
System.out.println("拿连接:" + conn);
System.out.println("-------------------------------");
JdbcUtil.close(conn, null, null);
conn = JdbcUtil.getConnection();
System.out.println("拿连接:" + conn);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}