zoukankan      html  css  js  c++  java
  • 【转】解决$Proxy0 cannot be cast to java.sql.Connection异常

    在模拟写数据库连接池的时候使用动态代理设计模式,然后出现了如题的错误,很是郁闷,最后经百度找到了如下的解决方法:
    解决:
    可以将 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();
            }
        }
  • 相关阅读:
    Java的 Annotation 新特性
    Java 枚举
    Java 泛型
    Linux kali信息探测以及 Nmap 初体验
    静态导入 ()
    Java foreach循环
    Java 可变参数
    炫酷的CSS3响应式表单
    关于CSS选择器连续性的问题
    简述ECMAScript6新增特性
  • 原文地址:https://www.cnblogs.com/shiguangmanbu2016/p/5932915.html
Copyright © 2011-2022 走看看