【问题标题】:In Java, what's the proper way of using an optional dependency without ClassNotFoundError?在 Java 中,在没有 ClassNotFoundError 的情况下使用可选依赖项的正确方法是什么?
【发布时间】:2023-02-13 22:46:20
【问题描述】:

我希望我的项目在启动时在后端库之间切换,可以选择不将它们都隐藏到生成的 Jar 中,同时具有对它们的完全编译可见性。 我还想避免使用 Class.forName 加载后端。

你能帮我理解这些是否会导致未着色库的 ClassNotFoundError 而哪些不会?

  1. 留下一个未使用的类字段,类型来自该库
  2. 留下未使用的方法,带有参数或从此库返回
  3. 在后端类中引用此库,该库将仅有条件地加载,如backend = isNewBackend ? new FancyBackend() : new OldBackend()

    如果所有这些都导致错误,是否有更简单的策略?

【问题讨论】:

  • 您是否正在考虑使用类路径上的两个库进行编译,然后在打包/部署期间从最终部署结果中删除其中一个?如果是,请问为什么?
  • 它是一个框架,用户启动 boostrap 进程指定框架应该使用哪个后端库。由于库非常重,避免将未使用的库隐藏到 jar 中是有益的。此外,它可以防止从另一个库中意外加载类,因为目前已知它们的静态初始化在 ClassLoader 上非常繁重。

标签: java reflection dependencies


【解决方案1】:

在 Java 中,在没有 ClassNotFoundError 的情况下使用可选依赖项的正确方法是什么?

简单的方法是使用Class.forName

我还想避免使用Class.forName 加载后端。

嗯……好吧。

你能帮我理解这些是否会导致未着色库的 ClassNotFoundError 而哪个不会?

如果我理解你的建议是正确的,那么它们都不会起作用。

留下一个未使用的类字段,类型来自这个库

加载定义该字段的类将触发加载定义该字段的库。

留下未使用的方法,带有参数或从此库返回

加载定义该方法的类将触发加载定义该字段的库。

在只会有条件地加载的后端类中引用此库,例如:

backend = isNewBackend ? new FancyBackend() : new OldBackend()

执行该计算的代码需要在类中定义。加载/运行您需要加载的代码两个都FancyBackendOldBackend 类。


如果您想避免显式调用 Class.forName,您可以将可选依赖项实现为自定义服务提供程序接口 (SPI)。这给了你额外的灵活性,但它是更复杂而不是简单地使用Class.forName

以下是 SPI 的一些参考资料:

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 2012-11-17
    • 2011-03-26
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多