繁体   English   中英

将第三方API集成到具有冲突依赖关系的Java应用程序中

[英]Integrating a third-party API into a Java application with clashing dependencies

我正在开发一个现有的应用程序,它具有相当多的外部JAR依赖项。 我需要增强它以与具有API的第三方应用程序集成。 可悲的是,API并没有得到很好的控制,并且还附带了大量自己的依赖项,其中一些依赖于我的。

我相信我应该使用类加载器解决这个问题,但我很难看到如何正确地构造它们。

为了简单起见,假设我们的myapp.jar具有hibernate3.jar依赖性,而vendor-api.jar具有hibernate2.jar依赖性(并假设它们不兼容)。

我的新代码将驻留在myapp.jar库中(尽管如果这会有帮助,它可能在一个单独的jar中)。 由于供应商API的工作方式,我的新代码需要从vendor-api.jar库扩展一个类。

如何以这样的方式构造类加载器:vendor-api.jar中的任何东西只访问它自己的依赖项,而我这边的任何东西只访问myapp.jar和依赖项?

谢谢,乔恩

我自己没有尝试过这个,但是从内存中来看,每个冲突类都需要在一个兄弟级的类加载器中,并且两者之间的任何通信都需要经历一个共同的祖先。 但是,祖先不能(AFAIK)“直接”引用其子类中的类,并且必须通过反射API访问它们。

沿着这些方向的东西应该起作用(干编码)YMMV。 评论和错误发现欢迎。

class Orchestrator {
    URL[] otherAppClasspath = new URL[] { new URL("file:///vendor-api.jar"),
                                          new URL("file:///hibernate2.jar"),
                                          new URL("file:///code-extending-vendor-api.jar" };
    URLClassLoader otherAppLoader = new URLClassLoader(otherAppClasspath);

    URL[] yourAppClasspath = new URL[] { new URL("file:///myapp.jar"),
                                         new URL("file:///hibernate3.jar") };
    URLClassLoader yourAppLoader = new URLClassLoader(yourAppClasspath);

    public void start() {
        Method yourAppEntryPoint = yourAppLoader.findClass("com/company/Main").getMethod("start", new Class[] { Orchestrator.class } );
        yourAppEntryPoint.invoke(null, new Object[] { this });
    }

    public static void main(String[] args) {
        new Orchestrator().start();
    }

    // define some abstracted API here that can be called from your app
    // and calls down into classes in the other app
    public String getSomeResultFromOtherApp(int someArgument) {
        Method otherAppAPI = otherAppLoader.findClass("com/company/ExtendingAPIClass").getMethod("getSomeResult", new Class[] { Integer.class });
        return (String)otherAppAPI.invoke(null, new Object[] { someArgument });          
    }

}

@ fd的答案提供了一个应该工作的技术机制 - 给予或采取一些拼写错误,异常处理等。

但是,我认为最好不要尝试这样做...除非你对第三方API的依赖仅限于极少数类的极少数方法。 您依赖的每个类都必须动态加载,并且必须以反射方式查找和调用每个方法。 太多,你的代码库将受到影响。

如果我是你,我会尝试以其他方式解决依赖问题:

  1. 尝试让第三方供应商使用hibernate3.jar
  2. 将您的应用程序更改为使用hibernate2.jar
  3. 重构,以便您的应用程序代码和第三方库位于单独的JVM或单独的Web应用程序中。

从你说的话来看,这可能很难。

使用OSGi可以长期帮助您。 这是我正在尝试的实现 - http://felix.apache.org

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM