转自:https://blog.csdn.net/fszeng2011/article/details/45218513
在练习数据库连接池时,遇到一个问题,之前同样使用过代理,方式一样都没有问题,代码如下。
/* * Title: getConnection Description: 重写方法:获取数据库连接池连接 * @return * @throws SQLException * @see javax.sql.DataSource#getConnection() */ @Override public Connection getConnection() throws SQLException { // 连接池中没有连接,创建连接 if (linkedList.size() == 0 && max <= jdbcConnectionMaxSize) { try { Class.forName(driver); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (int i = 0; i < jdbcConnectionInitSize; i++) { Connection con = DriverManager.getConnection(url, username, password); System.out.println("我第二次又创建了连接" + con); linkedList.add(con); max++; } } // 有,从集合中取出连接,当调用connection类对象的close()方法时将Connection对象重新放回集合中 if (linkedList.size() > 0) { Connection con1 = linkedList.removeFirst(); System.out.println("linkedList数据库连接池大小是" + linkedList.size()); /* * 返回一个Connection对象,并且设置Connection对象方法调用的限制, * 当调用connection类对象的close()方法时会将Connection对象重新收集放入linkedlist集合中。 */ return (Connection) Proxy.newProxyInstance(con1.getClass() .getClassLoader(),// 这里换成JdbcConnectionsPool.class.getClassLoader();也行 new Class[] { Connection.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (!method.getName().equalsIgnoreCase("close")) { return method.invoke(con1, args); } else { linkedList.add(con1); System.out.println(con1 + "对象被释放,重新放回linkedlist集合中!"); System.out.println("此时Linkedlist集合中有" + linkedList.size() + "个数据库连接对象!"); return null; } } }); } else { System.out.println("连接数据库失败!"); } return null; }运行时出现异常: $Proxy0 cannot be cast to java.sql.Connection
一直解决不了,上网查了下,原来Connection.getInterfaces() 与数据库驱动有关,数据库驱动不同 Connection.getInterfaces() 的结果也就不同,Connection.getInterfaces() 返回的是 Class[] 数组,此数组的第一个元素必须是Connection才能把创建的代理类转为Connection对象,否则就会报:java.lang.ClassCastException。
因为Connection本身就是一个接口,它的字节码符合第二个参数要求,于是把conn.getClass().getInterfaces();改成new Class[]{Connection.class},问题就解决了