Java 在Maven中,如何让孩子与父母有不同的依赖关系?

Java 在Maven中,如何让孩子与父母有不同的依赖关系?,java,maven,Java,Maven,我目前正在开发一个被另一个程序作为插件使用的程序。父程序(接受插件的程序)有它自己的依赖项,在我的例子中,最受关注的是番石榴。父插件的版本是21.0,而我正在创建的插件有一个依赖项,它需要版本20.0,并且似乎与较新的版本不配合,而且无论插件的pom中放了哪个版本,它似乎仍然使用父插件的版本21 Tl;dr:当父程序使用更高版本时,Maven有没有办法使用依赖项的较低版本(在我的例子中是20.0)?(这是否可能,因为插件很可能是通过反射接收的,因此将始终使用父依赖项?该插件是使用包含依赖项的依赖

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


Tl;dr:当父程序使用更高版本时,Maven有没有办法使用依赖项的较低版本(在我的例子中是20.0)?(这是否可能,因为插件很可能是通过反射接收的,因此将始终使用父依赖项?该插件是使用包含依赖项的依赖项构建的。)

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

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

如果您同时拥有(控制)托管应用程序和插件,那么您需要正确处理插件。说起来容易做起来难…
您应该寻找已经为您解决此问题的现有框架。
例如:,,还有更多…
另外,请查看以下问题:

简而言之——

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

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

编辑:
当您只能控制您的插件时,处理这种情况的另一个选项-

例如,您可以编写自己的类加载器,并在插件的入口点中使用它(以便使用该类加载器加载除入口点之外的所有插件类)。要做到这一点,您需要以这样的方式编写类加载器:它首先尝试从插件jar加载一个类,然后委托给其父加载器。这是可行的(实际上并不太困难),但违反了类装入器合同(首先委托给家长,只有在找不到时才自己装入)。

我仍然认为确保使用相同的依赖项更好、更健壮,特别是当应用程序有更新版本时

不能同时使用同一类的两个版本,除非它们在不同的包中。为了依赖库的缘故,您可以将该特定类/包的旧版本提取到您自己的项目中,但它也将被您自己的代码使用。谢谢,遗憾的是,获取插件的服务超出了我的控制,我必须处理当前的系统。所以,使用单独的类装入器仍然不可能解决这个问题?我对它们的了解是有限的,但是较低版本的源代码是否可以存储在插件jar中,并且只有在从较低版本的依赖项加载类时才能引用?例如,您可以编写自己的类加载器,并在插件的入口点使用它(因此,除了入口点之外的所有插件类都是使用这个类加载器加载的)。要做到这一点,你需要以这样的方式编写类加载器:它首先尝试从你的插件jar加载一个类,然后委托给它的父加载器。这是可行的(实际上并不太困难),但违背了类加载器的约定。