如何包含同一依赖项的两个不同版本? [英] How to include two different versions of the same dependency?

查看:422
本文介绍了如何包含同一依赖项的两个不同版本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Java进行ERP系统的自定义。在我的自定义中,我想使用Apache POI 3.10.1。因此我整合了罐子poi-3.10.1-20140818.jar和poi-ooxml-3.10.1-20140818.jar。

I am working on a customization for an ERP system in Java. In my customization I want to use Apache POI 3.10.1. Therefore I have integrated the jars poi-3.10.1-20140818.jar and poi-ooxml-3.10.1-20140818.jar.

但是,这些罐子包含几个类这已经包含在ERP系统的核心代码中,但有差异。

However, these jars contains several classes that are already included in the core code of the ERP System, but have differences.

如果核心ERP类覆盖POI类,则自定义会引发运行时异常。如果POI类覆盖核心类,核心功能可能会发生相同的情况。

If the core ERP classes override the POI classes, the customization throws a Runtime exception. Possibly the same will happens with a core functionality if the POI classes override the core classes.

处理这类问题的最佳做法是什么?

What is a best practice for dealing with a problem like this?

我的定制是一个相对孤立的功能。

My customization is a relatively isolated functionality.

推荐答案

有两种方法可以解决这个问题:

There are two approaches to solving this problem:


  1. 您可以将库与 ClassLoader 隔离开来加载其他版本的POI。现在,我假设ERP系统位于类路径上,因此您需要将库与系统类加载器隔离开来。您可以通过创建 <$的新实例来实现此目的c $ c> URLClassLoader 然后指向包含较新版本POI的jar文件。确保还添加所有瞬态依赖例如commons-codec以避免类加载问题。另请注意,瞬态依赖性本身可能具有瞬态依赖性。

  1. You can isolate the library from the ClassLoader that loads the other version of POI. for now, I assume that the ERP system is on the class path such that you need to isolate the library from the system class loader. You can do so by creating a new instance of an URLClassLoader which you then point to the jar files containing the newer version of POI. Make sure to also add all transient dependencies such as for example commons-codec to avoid class loading issues. Also, note that transient dependencies can have transient dependencies by themselves.

为了从类加载器隐藏类路径,您可以将引导类加载器设置为直接父级,由 null <表示/ code>:

In order to hide the class path from a class loader, you would set the bootstrap class loader as a direct parent which is represented by null:

new URLClassLoader(new URL[]{ new URL("poi-3.10.1-20140818.jar"), ... }, null);

使用此类加载器,您可以通过类似

With this class loader, you can query for the newer version POI classes by something like

Class.forName("org.apache.poi.hssf.usermodel.HSSFWorkbook", true, urlClassLoader);

用于检索新版本的 HSSFWorkbook 。但请注意,文字的任何对 HSSFWorkbook 的直接引用都将由执行类的类加载器解析,该类加载器当然会链接类的旧的,不兼容的版本。因此,您需要对所有代码使用反射。或者,您将一个类添加到 URLCLassLoader ,其中包含您的所有逻辑,并且仅通过反射调用此类。总的来说,这是一种更清洁的方法。例如,您可以添加一个实现引导类的类,例如 Callable ,然后您可以从任何不同的上下文中使用它,例如:

for retreiving the new version of the HSSFWorkbook. Note however that any direct reference to HSSFWorkbook by a literal would be resolved by the class loader of the executing class which would of course link the old, incompatible version of a class. Thus, you need to use reflection for all your code. Alternatively, you add a class to the URLCLassLoader which contains all your logic and only invoke this class via reflection. This is a cleaner approach, in general. For example, you could add a class that implements a bootstrap class such as Callable which you then can use from any different context as for example:

Callable<File> sub = (Callable<File>) Class.forName("pkg.Subroutine", 
                                                    true, 
                                                    urlClassLoader);
File convertedFile = sub.call();


  • 或者,您可以将第二个POI依赖关系重新打包到另一个名称空间。执行此操作后,类不再冲突,因为它们的名称不再相等。这可能是一种更简洁的方法,因为您可以使用来自同一类加载器的两个库,并避免反射。

  • Alternatively, you can repackage the second POI dependency into another name space. After doing this, the classes are not conflicting anymore as their names are not longer equal. This is probably a cleaner approach as you can then use both libraries from the same class loader and you avoid reflection.

    为了将依赖项重新打包到另一个名称空间,有一些工具,如 Maven Shade插件可以帮助您完成此任务。 jarjar 的替代方案是 ant Shadow插件 //www.gradle.org/rel =nofollow> Gradle 。

    For repackaging a dependency into another name space, there are tools like the Maven Shade plugin that can help you with this task. Alternatives are jarjar for ant or the Shadow plugin for Gradle.

    这篇关于如何包含同一依赖项的两个不同版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆