两个类MyConnectionHandler 和 MyDataSource,
运行MyConnectionHandler的main方法,结果报一个死循环的错。MyDataSource是写好的连接池,为了避免在连接池拿到的Connection调用close方法,对close的方法用代理进行修改。
如果连接池里的Connection数小于做测试时循环中的i时,正常;如果大于了,就报死循环的错。0 : com.mysql.jdbc.Connection@1f7d134 --- false
1 : com.mysql.jdbc.Connection@c7e553 --- false
2 : com.mysql.jdbc.Connection@1a0c10f --- false
3 : com.mysql.jdbc.Connection@e2eec8 --- false
4 : com.mysql.jdbc.Connection@aa9835 --- false
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at $Proxy0.toString(Unknown Source)
at java.lang.String.valueOf(String.java:2827)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at cn.itcast_test.jdbc.MyConnectionHandler.main(MyConnectionHandler.java:44)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at cn.itcast_test.jdbc.MyConnectionHandler.invoke(MyConnectionHandler.java:36)
... 4 more
Caused by: java.lang.reflect.UndeclaredThrowableException
at $Proxy0.toString(Unknown Source)
... 9 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at cn.itcast_test.jdbc.MyConnectionHandler.invoke(MyConnectionHandler.java:36)
... 10 more
Caused by: java.lang.reflect.UndeclaredThrowableException
at $Proxy0.toString(Unknown Source)
... 15 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at cn.itcast_test.jdbc.MyConnectionHandler.invoke(MyConnectionHandler.java:36)
... 16 more。
MyConnectionHandler handler = new MyConnectionHandler();
for (int i = 0; i < 6; i++) {
Connection conn = handler.getConnection(MyDataSource.openConnection());
System.out.println(i + " : " + conn + " --- " + conn.isClosed());
conn.close();
}
MyConnectionHandler :import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;public class MyConnectionHandler implements InvocationHandler {
private Connection realConnection;
private Connection warpedConnection;
public MyConnectionHandler() {
}
public Connection getConnection(Connection realConnection) {
this.realConnection = realConnection;
warpedConnection = (Connection)Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Connection.class},
this);
return warpedConnection;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
if ("close".equals(method.getName())) {
MyDataSource.free(warpedConnection);
return null;
} else {
return method.invoke(realConnection, args);
}
}
public static void main(String[] args) throws Exception {
MyConnectionHandler handler = new MyConnectionHandler();
for (int i = 0; i < 6; i++) {
Connection conn = handler.getConnection(MyDataSource.openConnection());
System.out.println(i + " : " + conn + " --- " + conn.isClosed());
conn.close();
}
}
}MyDataSource : public class MyDataSource {
private final static String url = "jdbc:mysql://localhost:3306/test";
private final static String user = "admin";
private final static String pwd = "admin";
private final static int initCount = 5;
private final static int maxCount = 10;
private static int curCount = 0;
private static LinkedList<Connection> connectionPool = new LinkedList<Connection>();
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
static {
try {
for (int i = 0; i < initCount; i++) {
connectionPool.addLast(getConnection());
curCount++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, pwd);
}
public static void free(Connection conn) {
connectionPool.addLast(conn);
}
public static Connection openConnection() throws SQLException {
synchronized(connectionPool) {
if (connectionPool.size() > 0) {
return connectionPool.removeFirst();
}
if (curCount < maxCount) {
curCount++;
return DriverManager.getConnection(url, user, pwd);
}
throw new SQLException("已没有链接");
}
}
}
这个你是不是可以控制一下呢
当connection连接数 大于了 做其他的处理 或提示信息 或等待连接
MyConnectionHandler handler = new MyConnectionHandler();
for (int i = 0; i < 6; i++) {
Connection conn = handler.getConnection(MyDataSource.openConnection());
System.out.println(i + " : " + conn + " --- " + conn.isClosed());
conn.close();
} 关键时我已经把这个conn给close掉了,事务会拦截close方法,然后把这个连接添加到LinkedList集合里。
如果连接池有5个,我打印第6个的时候,打印出的conn应该和第一个conn是同一个连接。问题是为什么报这个死循环的错
MyDataSource.free(warpedConnection);改成MyDataSource.free(realConnection);
如下
if ("close".equals(method.getName())) {
MyDataSource.free(realConnection);
return null;
} else {
return method.invoke(realConnection, args);
}
}
试过了,问题就出在这。改过了就好用了。