我有一个maven多模块项目,它有一个父pom项目和一堆模块。其中一个模块是“主模块”,其中包含所有库。所有其他模块都依赖于该模块并使用提供的库。
主模块是一个Bukkit插件,可以将其他模块作为扩展加载。这些扩展都使用自己的类加载器加载,但加载的类在加载器之间共享,以便能够相互依赖。他们也能够依赖其他Bukkit插件,因为他们的父类加载器是Bukkit的PluginClassLoader,它也在插件之间共享加载的类以允许交互。
这就是问题开始的地方:不同的插件可能使用相同的库,但是该库的类可能会被不同的类加载器加载,从而导致LinkageErrors和其他问题。
我解决这个问题的想法是通过maven-shade-plugin重新定位主模块中的库。对于仅由主模块使用的库,这可以正常工作。但是,重定位其他模块使用的库会导致运行时ClassNotFoundExceptions,因为模块仍然会搜索正常的包名而不是重定位的包名。 然后我尝试将导入更改为重定位的包,但我的IDE(IntelliJ)找不到类。
有没有人知道如何解决这个搬迁问题?或者可能是类加载问题的不同方法?
答案 0 :(得分:2)
5年后,在一个非常相似的背景下(Bukkit - > SpongeApi)我又遇到了这个问题,但这次我发现了(可能只是令人满意的)解决方案:
主模块的阴影版本是主要工件,因此依赖者只能看到重定位的类并且不知道原始的类名。这在我们的情况下没有任何区别,因为主模块无论如何都是提供的依赖,但它也防止消费者意外地直接使用重定位的类。 IntelliJ不关心重定位,因此它不知道新的重定位类。将着色版本作为辅助工件附加(shadedArtifactAttached选项设置为true)使依赖项再次对依赖项可见。
依赖模块必须应用与主模块相同的重定位规则,因此插件会将类名更正为运行时可用的类名。
这样IntelliJ不知道重定位,但也不需要知道。如有必要,可以在父pom中配置重定位,以便在所有项目中使用一致的规则。
答案 1 :(得分:1)
我有几乎完全相同的问题(根据这个问题的年龄判断)。虽然我没有为图书馆提供更清晰的解决方案来覆盖其他插件。我有一个解决方法,IntelliJ无法识别重定位的类。
为了阻止它抱怨,我将带阴影的jar(带有重定位)作为IntelliJ库添加到目标模块。 你可以这样做:
File > Project Structure... > Modules > (target module) > Dependencies
Add (green +) > 1. Jars or directories...
选择带阴影的jar。
虽然它似乎乍一看,但解决方案解决方法有一些注意事项:
project.build.finalName
)