两个类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("已没有链接");
}
}


解决方案 »

  1.   

    在传智播客上看的jdbc(37Java的动态代理及使用该技术完善连接代理.avi)视频上的内容,自己手写的一个,报上面的错,请教高手哪里出的问题
      

  2.   

    如果连接池里的Connection数小于做测试时循环中的i时,正常;如果大于了,就报死循环的错。
    这个你是不是可以控制一下呢
    当connection连接数 大于了  做其他的处理 或提示信息 或等待连接
      

  3.   

    这个时main方法:
    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是同一个连接。问题是为什么报这个死循环的错
      

  4.   

    这写的不对,
    MyDataSource.free(warpedConnection);改成MyDataSource.free(realConnection);
    如下
    if ("close".equals(method.getName())) { 
    MyDataSource.free(realConnection); 
    return null; 
    } else { 
    return method.invoke(realConnection, args); 


    试过了,问题就出在这。改过了就好用了。
      

  5.   

    你往池中加的应该是真实的连接,不应该是你包装后的连接,所以要用realConnection
      

  6.   

    你通过代理对象去调用你实际对象的方法 代理对象跟实际对象实现了同样的接口 代理对象的方法实际上就是通过method.invoke(realConnection, args); 去调用你实际对象的方法