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

时间:2011-03-05 12:18:57

标签: java api classloader

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

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

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

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

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

谢谢,乔恩

3 个答案:

答案 0 :(得分:1)

我自己并没有尝试过这种方法,但是从内存中来看,每个冲突类需要在一个兄弟级的类加载器中,并且两者之间的任何通信都需要通过一个共同的祖先。但是,祖先不能(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 });          
    }

}

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:0)

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