【问题标题】:How to have a child have a different dependency in Maven than parent?如何让孩子在 Maven 中与父母有不同的依赖关系?
【发布时间】:2017-11-29 19:07:42
【问题描述】:

我目前正在开发一个程序,该程序被另一个程序作为插件接收。父程序(接受插件的程序)有它自己的依赖项,在我的例子中,关注的是番石榴。父级的版本是21.0,而我创建的插件有一个需要20.0版本的依赖,并且似乎与较新的版本不配合,无论插件的pom中放入什么版本,它仍然好像用的是21的父版本。

Tl;dr:当父程序使用更高版本时,Maven 有什么方法可以使用较低版本(在我的情况下为 20.0)的依赖项? (这是否可能,因为插件可能会通过反射接收,因此将始终使用父依赖项?插件是在包含依赖项的情况下构建的。)

【问题讨论】:

  • 你不能同时使用同一个类的两个版本,除非它们在不同的包中。为了依赖库,您可能能够将该特定类/包的旧版本提取到您自己的项目中,但您自己的代码也将使用它。

标签: java maven


【解决方案1】:

Maven 是一个构建工具,它不会在运行时(即应用程序已经运行时)控制您的依赖关系。所以这不是 maven 问题,因此 maven 不是寻找解决方案的地方。

如果您无法控制托管应用程序,而只能控制您的插件,那么您别无选择,只能使用插件和应用程序共有的相同版本的依赖项。

如果您同时拥有(控制)托管应用程序和插件,那么您需要正确处理插件。说起来容易,做起来难……
您应该寻找已经为您解决问题的现有框架。
一些例子是:OSGiJPFPF4J,还有更多...
另外,请查看以下 SOF 问题:Best way to build a Plugin system with Java

简而言之-

这是在应用程序中支持插件的经典问题。
在我看来,最好的解决方案是将插件与托管应用程序隔离开来。这可以使用不同的类加载器来实现,当然还有反射。

您的应用程序正在运行,并且它的类以“常规”方式加载 - 这里没什么特别的。但是,为了在运行时将插件代码与应用程序的依赖项隔离开来,您需要使用不同的类加载器(例如URLClassLoader)加载插件类和依赖项。非常重要的是,这个类加载器没有你的应用程序的类加载器作为父类,否则你仍然会面临版本控制的冲突问题(就像你现在一样)。

编辑:
当您只能控制您的插件时,处理这种情况的另一种选择-
例如,您可以编写自己的类加载器并在插件的入口点中使用它(以便除了入口点之外的所有插件类都使用此类加载器加载)。为此,您需要编写类加载器,使其首先尝试从插件 jar 加载一个类,然后委托给它的父加载器。这是可行的(实际上并不太难),但违反了类加载器合同(首先委托给父级,只有在没有找到时才自行加载)。
我仍然认为确保使用相同的依赖项会更好,更健壮,特别是当应用程序具有更新版本时......

【讨论】:

  • 谢谢,遗憾的是,使用插件的服务超出了我的控制范围,我必须处理当前的系统。所以仍然不能使用单独的类加载器来解决这个问题吗?我对它们的了解是有限的,但是较低版本的源代码是否可以存储在插件 jar 中并仅在从较低要求的依赖项加载类时才被引用?
  • 例如,您可以编写自己的类加载器并在插件的入口点中使用它(以便除了入口点之外的所有插件类都使用此类加载器加载)。为此,您需要编写类加载器,使其首先尝试从插件 jar 加载一个类,然后委托给它的父加载器。这是可行的(实际上并不太难),但违反了类加载器合同。
猜你喜欢
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 2015-03-26
  • 1970-01-01
相关资源
最近更新 更多