在模拟写数据库连接池的时候使用动态代理设计模式,然后出现了如题的错误,很是郁闷,最后经百度找到了如下的解决方法:
解决:
可以将 getConnection() 方法内的 conn.getClass().getInterfaces() 换成 new Class[]{Connection.class} 即可。
在使用动态代理增强Connection连接对象的close方法时,我碰到了如题所示的异常。通过搜索我发现这个异常出现的原因在于我使用的mysql数据库驱动的问题,由于数据库驱动不同,Connection.class.getInterfaces()返回的结果也不同,它返回的是一个Class[]数组,然而此数组的第一个元素必须是Connection才能把创建的代理类转为Connection对象,否则就会报错。
Connection.getInterfaces() 与 new Class[]{Connection.class} 2个使用方式的原因:
原来Connection.getInterfaces() 与数据库驱动有关,数据库驱动不同 Connection.getInterfaces() 的结果也就不同;Connection.getInterfaces() 返回的是 Class[] 数组,此数组的第一个元素必须是Connection才能把创建的代理类转为Connection对象,否则就会报:java.lang.ClassCastException 了
所以这里我们可以采取一个替代方式替换Connection.class.getInterfaces(),即new Class[] { Connection.class },这样无论数据库驱动是什么版本的驱动,都能保证这个类型转换不出错。
代码(部分省略):
public class MyPool implements DataSource{
//ArrayList--底层是数组,方便查找,不方便增删
//LinkedList--底层是链表,方便增删,不方便查找
private static List<Connection> pool = new LinkedList<Connection>();
static{
try {
Class.forName("com.mysql.jdbc.Driver");
for(int i=0;i<5;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","123");
pool.add(conn);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public Connection getConnection() throws SQLException {
if(pool.size()==0){
for(int i=0;i<3;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","123");
pool.add(conn);
}
}
final Connection conn = pool.remove(0);
//在返回connection对象之前,利用动态代理改造Connection 的 close()方法
//返回代理对象
Connection proxy = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), new Class[]{Connection.class},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if("close".equals(method.getName())){
retConn(conn);
return null;
}else{
return method.invoke(conn, args);
}
}
});
System.out.println("获取了一个连接,池里还剩"+pool.size()+"个");
return proxy;
}
//还回连接
private void retConn(Connection conn) {
try {
if(conn!=null && !conn.isClosed()){
System.out.println("还了一个连接,池里还剩"+pool.size()+"个");
pool.add(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
}