其实也不是连接池,而且我还是不太清楚Connection的close应该干嘛,简单的实现了DataSource,并使用动态代理实现Connection的复用,Connection使用几次以后或者使用一段时间以后再真正的关闭。
代码如下:
package com.jiehoo.core;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
public class ReusedConnection implements InvocationHandler {
private Connection connection;
private Connection proxyConnection;
private boolean using;
private int usedCount;
private long createTime;
private int connectionTimeout;
private int maxUsedCount;
public ReusedConnection(Connection connection, int connectionTimeout, int maxUsedCount) {
this.connection = connection;
this.connectionTimeout = connectionTimeout;
createTime = System.currentTimeMillis();
this.maxUsedCount = usedCount;
proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
new Class[] { Connection.class }, this);
}
private boolean needClose() {
return usedCount > maxUsedCount || createTime – System.currentTimeMillis() > connectionTimeout * 1000;
}
public boolean isUsing() throws SQLException {
if (!using && needClose()) {
using = true;
close();
}
return using;
}
public Connection getConnection() {
return proxyConnection;
}
public void setUsing(boolean using) {
this.using = using;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.equals("close")) {
return close();
} else {
return method.invoke(connection, args);
}
}
private Object close() throws SQLException {
using = false;
if (!needClose()) {
connection.commit();
notifyAll();
} else {
connection.close();
}
return null;
}
}
package com.jiehoo.core;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
public class SimpleDataSource implements DataSource {
protected PrintWriter logWriter = new PrintWriter(System.out);
private String driver;
private String url;
private String user;
private String password;
private int minConnection;
private int maxConnection;
private int connectionTimeout;
private int getConnectionTimeout;
private List connections = new ArrayList();
private int loginTimeout;
private int connectionUseCount;
public SimpleDataSource(String driver, String url, String user, String password, int minConnection,
int maxConnection, int connectionTimeout, int getConnectionTimeout, int loginTimeout, int connectionUseCount) {
this.driver = driver;
this.url = url;
this.user = user;
this.password = password;
this.minConnection = minConnection;
this.maxConnection = maxConnection;
this.connectionTimeout = connectionTimeout;
this.getConnectionTimeout = getConnectionTimeout;
this.loginTimeout = loginTimeout;
this.connectionUseCount = connectionUseCount;
init();
}
private void init() {
try {
Class.forName(driver);
DriverManager.setLoginTimeout(loginTimeout);
for (int i = 0; i < minConnection; i++) {
createConnection();
}
} catch (SQLException e) {
e.printStackTrace(logWriter);
} catch (ClassNotFoundException e) {
e.printStackTrace(logWriter);
}
}
public Connection getConnection() throws SQLException {
Connection connection = getFreeConnection(false);
if (connection == null) {
synchronized (connections) {
if (connections.size() < maxConnection) {
connection = createConnection();
} else {
connection = getFreeConnection(true);
}
}
}
return connection;
}
public Connection getConnection(String username, String password) throws SQLException {
logWriter.write("Do not support this method.");
return null;
}
public PrintWriter getLogWriter() throws SQLException {
return logWriter;
}
public int getLoginTimeout() throws SQLException {
return loginTimeout;
}
public void setLogWriter(PrintWriter out) throws SQLException {
logWriter = out;
}
public void setLoginTimeout(int seconds) throws SQLException {
this.loginTimeout = seconds;
}
private Connection createConnection() throws SQLException {
Connection connection = DriverManager.getConnection(url, user, password);
ReusedConnection reusedConnection = new ReusedConnection(connection, connectionTimeout, connectionUseCount);
connections.add(reusedConnection);
reusedConnection.setUsing(true);
return reusedConnection.getConnection();
}
public void close() {
try {
for (int i = 0; i < connections.size(); i++) {
ReusedConnection reusedConnection = (ReusedConnection) connections.get(i);
reusedConnection.getConnection().close();
}
} catch (SQLException e) {
e.printStackTrace(logWriter);
}
}
protected synchronized Connection getFreeConnection(boolean waiting) throws SQLException {
Connection connection = null;
for (int i = 0; i < connections.size(); i++) {
ReusedConnection reusedConnection = (ReusedConnection) connections.get(i);
if (!reusedConnection.isUsing()) {
connection = reusedConnection.getConnection();
if (connection.isClosed()) {
connections.remove(i);
i–;
} else {
reusedConnection.setUsing(true);
break;
}
}
}
if (connection == null && waiting) {
try {
wait(getConnectionTimeout * 1000);
} catch (InterruptedException e) {
}
connection = getFreeConnection(false);
if (connection == null)
throw new SQLException("No more available connection.");
}
return connection;
}
}
2006年12月26日 at 23:15
如果能把你的轮子的总体设计思路最好是那么几张图表示一下的话,我想可以帮助更多的后来者 :em19:
2006年12月27日 at 07:53
呵呵,其实我现在还没有总体的思路或者设计,只是有一个简单的目标:快速添加应用功能
另外就是尽量自己写代码,尽可能少使用第三方的类库或者工具