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

问题描述

我正在使用 Java 对 ERP 系统进行自定义.在我的自定义中,我想使用 Apache POI 3.10.1.因此我已经整合了 jars 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.

然而,这些 jars 包含几个类,这些类已经包含在 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. 您可以将库与加载其他 POI 版本的 ClassLoader 隔离.现在,我假设 ERP 系统在类路径上,因此您需要将库与系统类加载器隔离.您可以通过创建 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 表示的直接父类:

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);

使用这个类加载器,您可以通过类似的方式查询新版本的 POI 类

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 用于 antShadow 插件 用于 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.

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

  • 09-03 03:26