实现自定义连接池需要具备的若干条件:
1. 定义一个类
2. 指定成员变量:
初始化连接数、
最大连接数、
当前连接数
连接池集合(可以用List实现)
3. 构造函数:循环创建3个连接
4. 写一个创建连接的方法(重点看)
5. 获取连接的方法
6. 释放连接的方法(这个方法被代理对象代替了,貌似就没什么卵用了)
详细实现:
1.定义一个类,命名随意,最好能望文生义
这里定义一个MyPool.java
2. 指定成员变量:
// 初始化连接数
private int init_count = 3;
// 最大连接数
private int max_count = 6;
// 当前连接数
private int current_count = 0;
// 定义连接池,用于存放所有的连接
private LinkedList<Connection> pool = new LinkedList<Connection>();
3.构造函数
构造函数中初始化3个连接,并加入连接池中
// 1.构造函数中 初始化连接池
public MyPool() {
//初始化连接 3个
for(int i=0; i< init_count; i++){
current_count++;
//把连接加入连接池
pool.addLast(createConnection());
}
}
4. 写一个创建连接的方法(重点看)
在这里,我们需要对创建的连接对象进行改造,添加额外的功能:
需求:我们希望在调用close()方法释放连接对象的时候,能够先将connection对象还回连接池
因此这里用到了一种设计模式:动态代理
实现代码如下:
public Connection createConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
final Connection con = DriverManager.getConnection("jdbc:mysql:///day18","root","123");
//对当前连接对象创建其代理对象
Connection proxy = (Connection) Proxy.newProxyInstance(
con.getClass().getClassLoader(), //类加载器
// con.getClass().getInterfaces(), //当目标对象是一个具体的类的时候,可以这样调用
/*
* 注意:对于被代理的对象来言
* 如果接收代理对象的是个类,直接调用con.getClass().getInterfaces()是没问题的
* 但如果接受代理对象的是个接口,那就要使用这种方法:new Class[]{Connection.class}
*/
new Class[]{Connection.class}, //因为目标对象Connection是一个接口,所以要用这样的方法
new InvocationHandler() { //当调用con对象的方法时,自动触发事务处理
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 方法返回值
Object result = null;
// 当前执行方法额方法名
String methodName = method.getName();
if("close".equals(methodName)){
System.out.println("当前close方法开始执行!");
//将连接对象放回连接池
pool.addLast(con);
System.out.println("连接已经还回,close方法执行完毕!");
}else{
//调用目标对象方法
result = method.invoke(con, args);
}
// 判断当前执行了close方法的时候,把连接放入连接池
return result;
}
});
return proxy;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
5. 获取连接的方法
public Connection getConnection(){
//1判断池中是否有连接,如果有,则直接从池中取出
if(pool.size() > 0){
return pool.removeFirst();
}
//2 如果连接池中没有:
/* 判断:如果当前连接数没有达到最大连接数,则创建新的连接
如果当前连接数已经达到上限,则抛出异常
*/
if(current_count < max_count){
// 记录当前使用的连接数
current_count++;
// 创建一个连接
return createConnection();
}else
throw new RuntimeException("当前连接数已经达到最大值!");
}
6. 释放连接的方法
public void releaseConnection(Connection con){
//1.判断池的数目,如果小于初始化连接数,就放入池中
if(pool.size() < init_count){
pool.addFirst(con);
}else{
//4.2 关闭
try {
current_count--;
con.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}