转自:https://blog.youkuaiyun.com/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},问题就解决了