数据库中连接数量有限,涉及频繁的连接的打开、关闭,影响程序的运行效率,所以需要对数据库连接进行管理,使用连接池管理。
自定义连接池
管理连接,维护了以下几个参数: 初始化数目(init_count)、最大连接数(max_count)、当前连接(current_count)、 连接池集合(pool)
/**
* 自定义连接池
* 自己维护一个一定数量的连接,提供get和释放连接方法
* @author wsk
*
*/
public class MyPool {
private int init_count = 3; //维护的连接数量
private int max_count = 6; //最大连接数量
private int current_count = 0; //当前连接数
private LinkedList<Connection> pool = new LinkedList<Connection>(); // 连接存放点
/**
* 初始化连接
*/
public MyPool(){
for(int i=0;i<init_count;i++){
pool.add(createConnection());
}
System.out.println("初始化连接数量"+init_count);
}
/**
* 创建连接方法
* @return
*/
private Connection createConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获取连接
*/
public Connection getConnection(){
// 判断连接池中是否还有连接
if(pool.size()>0){
System.out.println("从连接池中取出连接对象");
current_count++;
return pool.removeFirst();
}
// 判断是否超过最大连接数量
if(current_count<max_count){
System.out.println("连接池中初始化连接已经用完,新创建连接");
current_count++;
return createConnection();
}
// 超过最大连接数,抛出异常
throw new RuntimeException("超过最大连接数");
}
/**
* 释放连接
*/
public void realeaseConnection(Connection con){
// 判断当前连接池中数量是否小于初始化数量
if(pool.size()<init_count){
current_count--;
pool.addLast(con);
System.out.println("连接放入连接池");
}
// 当连接池中数量等于初始化连接数量,就释放连接
try {
if(current_count>0)
current_count--;
con.close();
System.out.println("连接已经释放");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
需要注意:上述代码有一个问题,当用户从连接池中拿出连接,但没有使用连接池中定义的realeaseConnection(con)方法释放连接,直接使用con.close()方法关闭连接就会存在问题。
改进方法:使用代理,对连接池中连接接口的close方法生成代理对象。
代理:如果对某个接口中的某个指定的方法的功能进行扩展,而不想实现接口里所有方法,可以使用(动态)代理模式!
Java中代理模式:静态/动态/Cglib代理(spring)
使用动态代理,可以监测接口中方法的执行!
/**
* 创建连接方法
* @return
*/
private Connection createConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
// 创建连接
final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
// 对连接对象创建代理对象
Connection proxy = (Connection)Proxy.newProxyInstance(
con.getClass().getClassLoader(), // 对应对象的类加载器
// con.getClass().getInterfaces(), // 目标对象是一个具体类时
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();
// 判断是否执行close方法
if("close".equals(methodName)){
if(pool.size()<init_count){
System.out.println("执行close方法,连接池没满,放入连接池");
// 放入连接池
pool.addLast(con);
}else{
System.out.println("执行close方法,连接池满,关闭连接");
result = method.invoke(con, args);
}
}else{
// 调用目标对象方法
result = method.invoke(con, args);
}
return result;
}
});
return proxy;
} catch (Exception e) {
throw new RuntimeException(e);
}
}