gpt4 book ai didi

java - 将 `META-INF/services` 用于驱动程序的内部管道

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:54:45 24 4
gpt4 key购买 nike

我开发了 Jaybird JDBC 驱动程序,今天我遇到了一个问题(JDBC-325How to configure Jaybird with hibernate),它与 Jaybird 如何加载它的一些组件以及 NetBeans 如何限制类加载有关。

这个问题与 Jaybird 使用 META-INF/services 中的条目加载自身部分的方式有关,并且 NetBeans 为 Hibernate 向导使用的类加载器明确忽略了这些文件(请参阅下面的详细信息).

我可以通过(也)尝试加载属于 Jaybird 实现一部分的硬编码插件列表,或将定义移至其他位置来解决此问题。

但是我想知道将 META-INF/services 用于内部目的是否像 Jaybird 那样奇怪(或错误)?

我也不明白为什么 NetBeans 会排除 META-INF/services 的加载? Drew 的评论似乎表明 NetBeans 在加载驱动程序时使用它来解决错误(请参阅 this issue ),尽管我认为最好由用户解决,包括驱动程序的所有依赖项。

问题详情

Jaybird 为支持的协议(protocol)使用插件,例如 Type 4 协议(protocol)、自定义 Type 4 Open Office 协议(protocol)、Type 2 嵌入式(本地)协议(protocol)和 Type 2 本地客户端协议(protocol)。我也相信第三方曾经使用它来提供将 Oracle 特定语法转换为 Firebird 语法的驱动程序。

所有这些插件都在 META-INF/services/org.firebirdsql.gds.impl.GDSFactoryPlugin 中列出,并以类似于 java.util.ServiceLoader 的方式加载(当前的 2.2.x 驱动程序仍然支持 Java 5,所以我们实际上并不使用 ServiceLoader)。对于即将发布的版本,我还计划将其用于支持的连接编码和(有线)协议(protocol)定义。这将允许“自定义”编码定义(例如扩展支持的编码,或使用替代编码)或不同的协议(protocol)实现(例如用于故障排除、自定义日志记录等)。

现在实际的问题是 Netbeans 向导 Hibernate Mapping Files and POJOs from Database 使用自定义类加载器 (org.netbeans.modules.hibernate.util.CustomClassLoader) ,并且这个类加载器忽略 META-INF/services 中的文件。请注意,只有此向导有问题,Netbeans 本身可以毫无问题地使用该驱动程序。

代码忽略 META-INF/services:

@Override
public URL findResource(String name) {
return name.startsWith("META-INF/services") ? null : super.findResource(name); //NOI18N
}

@Override
public Enumeration<URL> findResources(String name) throws IOException {
if (name.startsWith("META-INF/services")) { //NOI18N
return Collections.enumeration(Collections.<URL>emptyList());
} else {
return super.findResources(name);
}
}

这导致没有发现任何插件并且驱动程序没有协议(protocol),这导致 Netbeans 内部出现 NullPointerException,因为没有创建连接。

最佳答案

我认为 Netbeans 团队对该错误的修复是错误的。无缘无故地忽略特定目录中的文件是很糟糕的。主要在META-INF/services这样重要的目录下。这不是安全问题或类似问题。他们只是为了其他人写得不好的代码而保护他们。他们应该使用其他方式来做到这一点。我只能想象像您这样的人花了多长时间才找到这个问题的原因!

Service Provider API 是公开的,原因之一是:每个人都应该使用它!这是减少代码耦合的好方法,而且效果很好!我会尽可能使用它,并建议大家使用它。

并且 Java API 明确支持使用服务提供者机制添加 JDBC 驱动程序:

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver.

这还表明,预计在 JDBC 4.0 (2007) 之后创建的驱动程序会通过该机制提供入口。

虽然它没有说明您应该/不能提供后备方案。其他司机必须这样做,否则他们会遇到同样的问题。但他们这样做可能出于其他原因(支持旧版本的 JDBC API)。

所以您正在做正确的事情,如果支持该特定用例对您来说非常重要,那么您将需要维护该代码作为后备。否则,删除代码并添加一些文档,以便人们可以解决它。

关于java - 将 `META-INF/services` 用于驱动程序的内部管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18921352/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com