开发者社区> 问答> 正文

使用JNDI配置时,为什么在代码里面不能获取DruidDataSource对象

环境: spring boot 1.4.1, druid 1.1.10 ,tomcat 7.0.82

代码如下:

@Bean(value="dataSource") public DataSource dataSource() throws SQLException, NamingException { JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup(); DataSource dataSource = dataSourceLookup.getDataSource("java:comp/env/jdbc/oracle"); System.out.println(dataSource.getClass().getName()); //打印结果:com.alibaba.druid.pool.DruidDataSource DruidDataSource druidDataSource = (DruidDataSource)dataSource; // 这行报错 return druidDataSource; }

为什么这里我从JNDI中获取到dataSource 后,打印出来dataSource 确实是com.alibaba.druid.pool.DruidDataSource类型, 但后面一行我做强制转型的时候,就会报错:

java.lang.ClassCastException: com.alibaba.druid.pool.DruidDataSource cannot be cast to com.alibaba.druid.pool.DruidDataSource

请大神帮忙解答,感激不尽~~~~!

原提问者GitHub用户grace-233

展开
收起
山海行 2023-07-05 19:50:14 117 0
3 条回答
写回答
取消 提交回答
  • 在使用JNDI配置时,无法直接获取到 DruidDataSource 对象的原因是由于类加载器的问题。

    当您使用 JNDI 配置连接池时,Tomcat 使用其自己的类加载器来加载并实例化 DruidDataSource 对象。而在代码中,您使用了 Spring Boot 默认的类加载器(通常是 WebAppClassLoader)来加载 DruidDataSource 类。由于这两个类加载器是不同的实例,所以无法做强制类型转换。

    解决这个问题的一个方法是使用 JNDI 提供的 API 获取 DataSource 对象,并通过反射来获取 DruidDataSource 的相关属性。

    以下是一个示例代码,展示了如何通过反射获取 DruidDataSource 对象的属性:

    @Bean(value="dataSource")
    public DataSource dataSource() throws NamingException, NoSuchFieldException, IllegalAccessException {
        Context ctx = new InitialContext();
        DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/oracle");
        
        // 通过反射获取 DruidDataSource 对象
        Field unwrapField = dataSource.getClass().getDeclaredField("wrapped");
        unwrapField.setAccessible(true);
        Object wrappedDataSource = unwrapField.get(dataSource);
        
        if (wrappedDataSource instanceof DruidDataSource) {
            DruidDataSource druidDataSource = (DruidDataSource) wrappedDataSource;
            // 在这里可以对 druidDataSource 进行操作和设置
            return druidDataSource;
        }
        
        throw new IllegalArgumentException("The DataSource is not an instance of DruidDataSource");
    }
    

    上述代码通过使用 ctx.lookup 方法获取 DataSource 对象,然后通过反射获取 DruidDataSource 对象。接下来,您可以对 DruidDataSource 进行进一步的操作和设置。

    请注意,这种方法需要使用反射来获取 DruidDataSource 对象的属性,因此需要确保您的代码在安全性和可维护性方面进行充分的验证和测试。

    2023-07-30 15:15:21
    赞同 展开评论 打赏
  • 北京阿里云ACE会长

    如果您使用JNDI配置Druid连接池,那么在代码中获取 DruidDataSource 对象时,应该使用 javax.naming.InitialContext 类,而不是直接创建 DruidDataSource 对象。

    2023-07-30 15:09:20
    赞同 展开评论 打赏
  • 研究了一下tomcat的类加载机制,tomcat中配置的连接池是使用URLClassLoader加载的。项目中使用的是WebappClassLoader加载的,所以这里肯定是没法强制转型的,因为是不同的对象了。 应该是没法获取dataSource实例对象了。。

    原回答者GitHub用户grace-233

    2023-07-06 11:09:13
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载