环境: 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
在使用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 对象的属性,因此需要确保您的代码在安全性和可维护性方面进行充分的验证和测试。
如果您使用JNDI配置Druid连接池,那么在代码中获取 DruidDataSource 对象时,应该使用 javax.naming.InitialContext 类,而不是直接创建 DruidDataSource 对象。
研究了一下tomcat的类加载机制,tomcat中配置的连接池是使用URLClassLoader加载的。项目中使用的是WebappClassLoader加载的,所以这里肯定是没法强制转型的,因为是不同的对象了。 应该是没法获取dataSource实例对象了。。
原回答者GitHub用户grace-233
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。